While working on my project I came across a problem regarding tabs and tabgroup in PySimpleGUI.
Is there a function that returns currently selected tab?
Having many tabs I would like being able to select each of them (but not at the same time) and return the key of the currently selected one/active one.
I've tried .Get() and .Select() but seems like these don't do it or maybe I'm doing something wrong? Please keep in mind I'm a total beginner.
I also made sure to enable events in every tab.
I did something like this: curr_sel_tab= tab_group.find_key_from_tab_name(tab_group.Get()) but it returns the name of the tab instead of the key.
Basically my app is connected to a database. What I'm trying to do is to select a row in a tab(1,2,3 or 4) and delete it. But in order to do it I need a key of the tab(I guess).
Below you can find a fragment of code I stuck upon as well as a screenshot of my app.
import PySimpleGUI as sg
import baza # external file with my databse
sg.theme("GreenTan")
left_col = [sg.Button("Create")],[sg.Button("Read")],[sg.Button("Update")],[sg.Button("Delete")]
data = baza.get_db_obiad()
print(data)
headings2 = ['Id', 'Name', '1', '2', '3']
layout_1 = [[sg.Table(values=data[0:][:], headings=headings2, max_col_width= True,
auto_size_columns=False,
display_row_numbers=False,
enable_events=True,
justification='c',
alternating_row_color='lightyellow',
key='-TAB_1-',
row_height=35)]]
data1 = baza.get_db_podkladka()
headings3 = ['Id','Name']
layout_2 = [[sg.Table(values=data1[0:][:], headings=headings3, max_col_width= True,
auto_size_columns=False,
display_row_numbers=False,
enable_events=True,
justification='c',
alternating_row_color='lightyellow',
key='-TAB_2-',
row_height=35)]]
data2 = baza.get_db_mieso()
headings4 = ['Id','Name']
layout_3 = [[sg.Table(values=data2[0:][:], headings=headings4, max_col_width= True,
auto_size_columns=False,
display_row_numbers=False,
enable_events=True,
justification='c',
alternating_row_color='lightyellow',
key='-TAB_3-',
row_height=35)]]
data3 = baza.get_db_dodatki()
headings5 = ['Id','Name']
layout_4 = [[sg.Table(values=data3[0:][:], headings=headings5, max_col_width= True,
auto_size_columns=False,
display_row_numbers=False,
enable_events=True,
justification='c',
alternating_row_color='lightyellow',
key='-TAB_4-',
row_height=35)]]
tab_group = sg.TabGroup([[sg.Tab("Tab 1", layout_1),
sg.Tab("Tab 2", layout_2),
sg.Tab("Tab 3", layout_3),
sg.Tab("Tab 4", layout_4)]],
enable_events=True)
right_col = [[tab_group]]
layout = [[sg.Column(left_col, justification="c"), sg.Column(right_col)]]
window = sg.Window("", layout).Finalize()
window.Maximize()
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == "Exit":
break
elif event == "Create":
pass
elif event == "Read":
pass
elif event == "Update":
pass
elif event == "Delete":
if sg.popup_yes_no("Are you sure you want to delete this record?"):
curr_sel_tab= tab_group.find_key_from_tab_name(tab_group.Get())
print(curr_sel_tab)
else:
break
window.close()
Screenshot from my app
I had a similar issue! I was able to figure out that the values object contains the key of the tab that has been clicked on. You would just need to figure out what index its at. Before you do that, it would be a good idea to give each tab a key so that you know what tab was clicked on. Made some edits to your code below. Notice how I added the keys to teach tab:
tab_group = sg.TabGroup([[sg.Tab("Tab 1", layout_1, key= "tab1"),
sg.Tab("Tab 2", layout_2, key="tab2"),
sg.Tab("Tab 3", layout_3, key="tab3"),
sg.Tab("Tab 4", layout_4, key="tab4")]],
enable_events=True)
If you print out the values object and "Tab 1" is clicked, then you will see its key, "tab1" in this case, inside the values object. Same applies for the other tabs if they are clicked.
Hope this helps!
Related
i have written the right code in python simple gui, but after running the code, only one row is displayed and the whole table is not shown i dont know why.this is what is displayed after running the code.
import PySimpleGUI as sg
rows=[
["CULTUS","4","3500","300","550"],
["SONATA","3","5000","350","750"],
["KIA Sportage","3","6000","500","700"],
["Yaris","5","4000","300","600"],
["HONDA CIVIC","5","5500","300","600"],
["Pajero","2","7000","500","700"]
]
header =[
["Model", "Available", "Price/Day","Liability Insurance/Day", "Comprehensive Insurance/Day"]
]
layout=[[sg.Table(
values=rows,
headings=header,
size=(500,300),
key="-TABLE-",)
],
[sg.OK(),sg.Cancel()]
]
window = sg.Window('TG Enterprises', layout ,size=(600,400))
event, values = window.read()
if event == 'Cancel':
window.close()
print(event,values)
this is my code ,can anyone please help me what is wrong with this code and what can i do to make it right?
I cut out some of the text to make it easier to comprehend, but basically it turns out that your attempt was very close.
The main error was the header was a list containing a list. whereas it should just have been a list.
so using boilerplate i made a working example for you like this:
import PySimpleGUI as sg
rows=[
["CULTUS","4","3500","300","550"],
["SONATA","3","5000","350","750"],
["KIA Sportage","3","6000","500","700"],
["Yaris","5","4000","300","600"],
["HONDA CIVIC","5","5500","300","600"],
["Pajero","2","7000","500","700"]
]
header =["Model", "Available", "Price","Liability", "Comprehensive"]
layout = [[sg.Text(x) for x in header],
[sg.Table(values=rows,
headings=header,
max_col_width=25,
auto_size_columns=True,
justification='right',
alternating_row_color='lightblue',
key='table')],
[sg.Button('Add'), sg.Button('Delete')]]
window = sg.Window('Table example').Layout(layout)
while True:
event, values = window.Read()
if event is None:
break
print(event, values)
window.Close()
and the result looks like this:
note: I didnt try out the buttons or any other logic. I just provided an example of the correct formatting example.
I use hide_row() element or feature in my code to hide row but it work only one time when i connected to Retreat button or Retreat key, when i clicked again or in the 2nd time it's not work (see the code or try it to understand what i mean) how make it work continuously not only one time or is there another way to undo or delete section or row.
import PySimpleGUI as sg
layout = [
[sg.Col([[sg.T('Enter your name:'),sg.In()],[sg.Btn('Ok'), sg.Btn('Exit'),
sg.Btn('Add new row')]],k='col_key')]
]
window = sg.Window('Test', layout)
while True:
event, values = window.read()
if event in ('Exit' ,sg.WIN_CLOSED):
break
if event == ('Add new row'):
window.extend_layout(window['col_key'],[[sg.T('Enter your name:', key='new_raw'),(sg.In())]])
window.extend_layout(window['col_key'],[[sg.Btn('Retreat', key='re')]])
if event == ('re'):
window['new_raw'].hide_row()
window['re'].hide_row()
window.close()
It is caused by new element with duplicate key when add new row again, so it wll always find the first element when you call window[new_key].
Should use different key for different element when you create a new element.
Key of new element will be replace by
element.Key = str(element.Key) + str(self.UniqueKeyCounter)
So key for new elements will be
'new_raw', 're', 'new_raw0', 're1', 'new_raw2', 're3', 'new_raw4', 're5', ...
you can check it by
>>> window.key_dict
{
...
'new_raw': <PySimpleGUI.PySimpleGUI.Text object at 0x000001D3A5B80FA0>,
'new_raw0': <PySimpleGUI.PySimpleGUI.Text object at 0x000001D3A6FA1280>,
'new_raw2': <PySimpleGUI.PySimpleGUI.Text object at 0x000001D3A6FA1220>,
're': <PySimpleGUI.PySimpleGUI.Button object at 0x000001D3A6FA1CD0>,
're1': <PySimpleGUI.PySimpleGUI.Button object at 0x000001D3A6FA1340>,
're3': <PySimpleGUI.PySimpleGUI.Button object at 0x000001D3A6FA11F0>}
After new row generated, the key of button Retreat is not 're', but starts with 're' and ends with an index.
Update code as following
import PySimpleGUI as sg
layout = [
[sg.Col([[sg.T('Enter your name:'),sg.In()],[sg.Btn('Ok'), sg.Btn('Exit'),
sg.Btn('Add new row')]],k='col_key')]
]
window = sg.Window('Test', layout)
index = 0
while True:
event, values = window.read()
if event in ('Exit' ,sg.WIN_CLOSED):
break
if event == ('Add new row'):
window.extend_layout(window['col_key'],[[sg.T('Enter your name:', key=f'new_raw {index}'),(sg.In(key=f'input {index}'))]])
window.extend_layout(window['col_key'],[[sg.Btn('Retreat', key=f're {index}')]])
index += 1
if event.startswith('re'):
i = event.split(' ')[-1]
window[f'new_raw {i}'].hide_row()
window[f're {i}'].hide_row()
window.close()
There's still problem for old rows hidden will still be kept in memory, so occupied memory will grow higher and higher if you add new row again and again, but it's not question to be discussed here.
I got a table in PySimpleGui (sg.Table) and I want to add the option to hide/delete a column of that table. I found a way to do this with the data of the table, but it seems you can't edit the headings of a table on the fly. At least the .update() method doesn't provide one.
My first thought: Creating a new window with new data, without that column. But that seems like a laborious way of doing things...
Is there any clever way to do it?
You can configure ttk.Treeview (sg.Table) with option displaycolumns to select which columns are actually displayed and determines the order of their presentation. Add one more 'Row' before your displaycolumns list if you specified display_row_numbers=True.
from copy import deepcopy
import PySimpleGUI as sg
sg.theme("DarkBlue3")
newlist = [
[f"Cell ({row:0>2d}, {col:0>2d})" for col in range(8)]
for row in range(10)
]
COL_HEADINGS = ["Date", "Ref", "ID", "Owner", "Customer", "Price", "Size", "Path"]
layout = [
[sg.Table(
values=newlist,
headings=COL_HEADINGS,
max_col_width=25,
num_rows=10,
alternating_row_color='green',
display_row_numbers=True,
key='-TABLE-',
enable_click_events=True,
justification='center',
)],
[sg.Button('Hide Customer')],
]
window = sg.Window('Table', layout, finalize=True)
table = window['-TABLE-']
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == 'Hide Customer':
window[event].update(disabled=True)
displaycolumns = deepcopy(COL_HEADINGS)
displaycolumns.remove('Customer')
table.ColumnsToDisplay = displaycolumns
table.Widget.configure(displaycolumns=['Row']+displaycolumns)
window.close()
In my code, Im trying to make a calculator. So there is a 1 button which when pressed, updates the Question: text by adding 1 to it's text. So when I press 1, the text will convert from Question: to Question: 1. But its not updating. I have faced this problem before too. I think when I do the .update, it will only update the value till its the same number of letters as the text already has. If it has 2 letters and I try to .update('123'), it will only update to 12. Is there any way to get around this???
import PySimpleGUI as sg
layout = [
[sg.Text('Question: ', key='-IN-')],
[sg.Text('Answer will be shown here', key='-OUT-')],
[sg.Button('1'), sg.Button('2'), sg.Button('3')],
[sg.Button('4'), sg.Button('5'), sg.Button('6')],
[sg.Button('7'), sg.Button('8'), sg.Button('9')],
[sg.Button('Enter'), sg.Button('Exit')]
]
window = sg.Window('calculator', layout)
while True:
event, values = window.read()
if event is None or event == 'Exit':
break
elif event == '1':
bleh = window['-IN-'].get()
teh = f'{bleh}1'
window['-IN-'].update(value=teh)
window.close()
As above comment, Example like this,
import PySimpleGUI as sg
layout = [
[sg.InputText('Question: ', readonly=True, key='-IN-')],
[sg.Text('Answer will be shown here', key='-OUT-')],
[sg.Button('1'), sg.Button('2'), sg.Button('3')],
[sg.Button('4'), sg.Button('5'), sg.Button('6')],
[sg.Button('7'), sg.Button('8'), sg.Button('9')],
[sg.Button('Enter'), sg.Button('Exit')]
]
window = sg.Window('calculator', layout)
input = window['-IN-']
while True:
event, values = window.read()
if event is None or event == 'Exit':
break
elif event in '1234567890':
bleh = window['-IN-'].get()
teh = f'{bleh}{event}'
input.update(value=teh)
input.Widget.xview("end") # view end if text is too long to fit element
window.close()
I'm new to PYSimpleGUI and python GUI programming in general. I have made a simple settings relief that I'd like to have expand and contract as needed. Is there a way to get the 3rd picture to resemble the 1st once the elements have been marked visible then not visible?
Picture 3 has the relief still expanded. Is there a way to have it contract again? Thank you!
Please see the code below:
import PySimpleGUI as sg
def mkWindow():
# Layout for the Advanced relief
layout = [
[sg.Frame(layout=[
[(sg.Text('Show Advanced Settings', size=[25, 1]))],
[sg.Radio('No', "RADIO2", key='_radio_no2_', enable_events=True, default=True, size=(5,1)), sg.Radio('Yes', "RADIO2", enable_events=True, key='_radio_yes2_')],
[(sg.Output(key='_out_', size=[25, 27], visible=False))]], title='Advanced',title_color='red', relief=sg.RELIEF_SUNKEN)]]
window = sg.Window('Output Test', layout, finalize=True)
while True:
event, wvalues = window.read()
if(event=='_radio_yes2_'):
window.Element('_out_').Update(visible=True)
if(event=='_radio_no2_'):
window.Element('_out_').Update(visible=False)
if(event==sg.WIN_CLOSED):
break
window.close()
mkWindow()
Edited to add code. I pared it down to be just the affected frame that still produces the effect when the GUI is generated.
It really is all in the docs. There is a pin function that does exactly what I was looking for. If added within any kind of frame, the frame auto-sizes as expected. I believe it does shift things within the collapse function by just a bit because it's a layout element within a larger layout, but I got around this by putting the other elements together in another element so they aligned ok. Hope this helps someone out there.
Cookbook where I got the relevant code.
Code for convenience/in case link breaks at some point:
import PySimpleGUI as sg
Demo - "Collapsible" sections of windows
This demo shows one techinique for creating a collapsible section (Column) within your window.
It uses the "pin" function so you'll need version 4.28.0+
A number of "shortcut aliases" are used in the layouts to compact things a bit.
In case you've not encountered these shortcuts, the meaning are:
B = Button, T = Text, I = Input = InputText, k = key
Also, both methods for specifying Button colors were used (tuple / single string)
Section #2 uses them the most to show you what it's like to use more compact names.
To open/close a section, click on the arrow or name of the section.
Section 2 can also be controlled using the checkbox at the top of the window just to
show that there are multiple way to trigger events such as these.
Copyright 2020 PySimpleGUI.org
SYMBOL_UP = '▲'
SYMBOL_DOWN = '▼'
def collapse(layout, key):
"""
Helper function that creates a Column that can be later made hidden, thus appearing "collapsed"
:param layout: The layout for the section
:param key: Key used to make this seciton visible / invisible
:return: A pinned column that can be placed directly into your layout
:rtype: sg.pin
"""
return sg.pin(sg.Column(layout, key=key))
section1 = [[sg.Input('Input sec 1', key='-IN1-')],
[sg.Input(key='-IN11-')],
[sg.Button('Button section 1', button_color='yellow on green'),
sg.Button('Button2 section 1', button_color='yellow on green'),
sg.Button('Button3 section 1', button_color='yellow on green')]]
section2 = [[sg.I('Input sec 2', k='-IN2-')],
[sg.I(k='-IN21-')],
[sg.B('Button section 2', button_color=('yellow', 'purple')),
sg.B('Button2 section 2', button_color=('yellow', 'purple')),
sg.B('Button3 section 2', button_color=('yellow', 'purple'))]]
layout = [[sg.Text('Window with 2 collapsible sections')],
[sg.Checkbox('Blank checkbox'), sg.Checkbox('Hide Section 2', enable_events=True, key='-OPEN SEC2-CHECKBOX')],
#### Section 1 part ####
[sg.T(SYMBOL_DOWN, enable_events=True, k='-OPEN SEC1-', text_color='yellow'), sg.T('Section 1', enable_events=True, text_color='yellow', k='-OPEN SEC1-TEXT')],
[collapse(section1, '-SEC1-')],
#### Section 2 part ####
[sg.T(SYMBOL_DOWN, enable_events=True, k='-OPEN SEC2-', text_color='purple'),
sg.T('Section 2', enable_events=True, text_color='purple', k='-OPEN SEC2-TEXT')],
[collapse(section2, '-SEC2-')],
#### Buttons at bottom ####
[sg.Button('Button1'),sg.Button('Button2'), sg.Button('Exit')]]
window = sg.Window('Visible / Invisible Element Demo', layout)
opened1, opened2 = True, True
while True: # Event Loop
event, values = window.read()
print(event, values)
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event.startswith('-OPEN SEC1-'):
opened1 = not opened1
window['-OPEN SEC1-'].update(SYMBOL_DOWN if opened1 else SYMBOL_UP)
window['-SEC1-'].update(visible=opened1)
if event.startswith('-OPEN SEC2-'):
opened2 = not opened2
window['-OPEN SEC2-'].update(SYMBOL_DOWN if opened2 else SYMBOL_UP)
window['-OPEN SEC2-CHECKBOX'].update(not opened2)
window['-SEC2-'].update(visible=opened2)
window.close()