Question
Win 10
3.6
3.27.0
Hi,
I'd like to update values and headings in the Table layout.
I define
tab2_layout = [[sg.Table( values=data,
headings=header_list,
auto_size_columns=False,
key='result_table')]]
I show table in window and all is fine.
However, I update data variable and header_list variable.
I use call:
window.FindElement('result_table').Update(values=data_new)
but it only updates data.
I tried to extend Update() in pysimplegui.py and then call:
window.FindElement('result_table').Update(values=new_data,headings=new_header_list)
but I do not know the logic etc.
Question:
How to update column names in Table?
There is not currently a way to modify the table headers using a call to Update.
I'll look at what it would take to add as an enhancement or see if I can find a workaround for you.
If you come up with some sensible solution I'm all ears :).
At the moment, I just make sure I know all upfront and keep header constant.
Tx.
Just noticed this request after replying to a newer issue. See my idea in https://github.com/PySimpleGUI/PySimpleGUI/issues/1419.
I'm definitely interested in a solution to this issue too. I will check out chris's idea in #1419 and see if I can figure out how to use it to modify the Update method to work for Table headings.
Yea, this is on the list.
Rather than modifying Update directly, I recommend locating the code in your user code. I exposed all of the underlying Widgets using the universally available element.Widget. All ports should support this. It will enable you to directly manipulate the Qt/Ikinter/Wx/Remi widget (at least that's the idea and I'm pretty sure I modified all of the code correctly.... BUT I may not have, so be sure and print out the value of that variable before trying to use it..
Locating the code in your files enables you to upgrade PySimpleGUI at any time without affecting your change., If you fork, then you're stuck with that release unless you're willing to merge your changes in with each release.
I think this is user solvable. Let me know if you are unable to access the Widget to get the task done.
MIke, I will look into your solution above. That is all new to me. I am using PySimpleGUI with TK. FYI, I was able to successfully change the column headings while running PySimpleGUI.py and clicking the Normal Button in your demo GUI by editing the Table Update method starting on line 4133 adding/editing the starred lines below. WIth these edits, I am able to update the headings using a list. The only extra thing that might be nice is an error trap for when len(headings) > number of columns of data. It errors out in that case, but would be easy to trap by just using the first several headings in the list until you reach number of columns of data. The Update method works fine if len(headings) <= numberofcolumns.
*4133 def Update(self, values=None, headings=None, num_rows=None, visible=None, select_rows=None):
4164 if select_rows is not None:
4165 rows_to_select = [i+1 for i in select_rows]
4166 self.TKTreeview.selection_set(rows_to_select)
*4167 if headings is not None:
*4168 for ii, nn in enumerate(headings):
*4169 self.TKTreeview.heading(ii, text=nn)
10521 elif event == 'Normal':
10522 #window.Normal()
*10523 window.Element('_table_').Update(headings=['L1', 'C1', 'time', 'freq'])
Mike,
Sorry for the barrage of messages, but as you can tell I'm super motivated to get Tables working. I am oh so close with my GUI thanks to PySimpleGUI, but there are several Table issues I need to resolve to be able to define an empty table, then dynamically update it, including updating both the column headings (names) and the numbers of columns, based upon GUI events.
Related to this effort, I think I found a typo in the TK Table element definition. I changed line 7710 as shown below, and it seems to have fixed a problem I was having.
7710 old: width = max(column_widths[i], len(heading))
7710 new : width = max(column_widths[i], len(headings))
Thanks,
Jason
FYI, after making all these changes, I have noticed that I haven't been seeing another known problem of Tables, which is the headings going into spasms when you mouse over them. Very promising! But, as you mentioned, I'd rather not create my own fork and instead get all these things put into the official release (for various reasons, including the fact that you will definitely implement it better than me!).
Oh wow, if you solved the "spastic headers" problem, that will get in there quick.
I'm surprised you can't create an empty table. One thing you can do is literally create the table with 1 row of "empty" data. Then use Update to change the table later.
My "problem" with additions to features is the porting effort to span them across the other 3 ports so that the SDK remains portable. I already know a number of features need cross-porting.
I don't think I'm communicating the message correctly regarding changes to PySimpleGUI.....
My suggestions have been attempts to get you to create solutions that do not involve modifying any PySimpleGUI.py code on your part, but instead make the SAME CALLS inside YOUR code. In other words, if you can change Update to make this work, then you can do the same operation inside YOUR code rather than calling Update.
I'll drop the bug fix in the next release. I haven't looked at it yet. Thanks for pointing it out.
Hi Mike,
No, you are definitely clear when you say I should be able to not have to modify the Update method in PySimpleGUI. I am fairly new to it, and was unaware of the element.Widget capability until your comment above, but I will definitely pursue that track. However, in parallel, it would be great if you do pursue a more general solution as well. If you can, it would address table issues #1419 #1451 #1307 and others.
To summarize the changes I made so far to PySimpleGUI, just as experiments before I try element.Widget approach:
7708 – added default column width of 10 in case the values are empty list. This will help to define a table with empty values (still need some headings defined). Solution based upon https://github.com/PySimpleGUI/PySimpleGUI/issues/1451
7708 if element.Values == []: column_widths[i] = 10 # this will use 10 as default columnwidth value
7710 – I think this was a typo and changed heading to headings
7710 width = max(column_widths[i], len(heading)) >>>>>>> width = max(column_widths[i], len(headings))
4167 – added lines to allow for table update method to update column headings. https://github.com/PySimpleGUI/PySimpleGUI/issues/1307 and https://github.com/PySimpleGUI/PySimpleGUI/issues/1419
4167 if headings is not None:
for ii, nn in enumerate(headings):
self.TKTreeview.heading(ii, text=nn)
Thanks again for your great support and work!
-Jason
Can you verify the code you changed was this section of the Table Element:
headings = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0]
for i, heading in enumerate(headings):
treeview.heading(heading, text=heading)
if element.AutoSizeColumns:
width = max(column_widths[i], len(heading))
else:
try:
width = element.ColumnWidths[i]
except:
width = element.DefaultColumnWidth
treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor)
if so, then len(heading) is the correct code I'm afraid. len(headings) counts the number of headings you have in the table. len(heading) gets the length of a single heading, in characters.
What this code does is set the size of each column based on the number of characters in the heading (singular).
It's weird that it fixed the spastic problem. I've not been able to duplicate it recently.
@jbiz25 I'm doing the best I can here. Rattling off 4 bugs you would like me to fix right away isn't going to have a positive impact.
I'm right in the middle of trying to get the doc strings done, something the benefits everyone. I thought I announced that pretty well too.
The kinds of bugs taking priority at this moment at crashes and stuff that cannot be done in user code.
It's not that I don't want to work on your problems.... it's a matter of priority. I have to pick and choose. If you don't think you can fix this in your code and must make PySimpleGUI.py changes, fork the code and go crazy. I'll eventually get to these and at that point you can get back to the main code base.
Maybe I'm not being clear on what I mean by "located in user code".
If you want to take the "completely replace Update" method, then you will copy the Table.Update method into YOUR .py file.
Here is that code.... you're familiar with it since you've been modifying it:
def Update(self, values=None, num_rows=None, visible=None, select_rows=None):
"""
Changes some of the settings for the Table Element. Must call `Window.Read` or `Window.Finalize` prior
:param values:
:param num_rows:
:param visible: (bool) control visibility of element
:param select_rows:
"""
if values is not None:
children = self.TKTreeview.get_children()
for i in children:
self.TKTreeview.detach(i)
self.TKTreeview.delete(i)
children = self.TKTreeview.get_children()
# self.TKTreeview.delete(*self.TKTreeview.get_children())
for i, value in enumerate(values):
if self.DisplayRowNumbers:
value = [i + self.StartingRowNumber] + value
id = self.TKTreeview.insert('', 'end', text=i, iid=i + 1, values=value, tag=i % 2)
if self.AlternatingRowColor is not None:
self.TKTreeview.tag_configure(1, background=self.AlternatingRowColor)
self.Values = values
self.SelectedRows = []
if visible is False:
self.TKTreeview.pack_forget()
elif visible is True:
self.TKTreeview.pack()
if num_rows is not None:
self.TKTreeview.config(height=num_rows)
if select_rows is not None:
rows_to_select = [i+1 for i in select_rows]
self.TKTreeview.selection_set(rows_to_select)
Replace self with the element you created. You can either save the table element info, of you do a Window.FindElement to get your Table Element.
We've already discussed that element.Widget is the widget being used by the Element. So, replace all of the TKTreeview with Widget.
Then feel free to modify the hell out of your very own Update method.
Unless you do some fancy class stuff, you will need to CALL your new update and you will pass in your Table element, changing the first parameter from self to element.
Sorry there are no doc strings yet on the Table Element. I'm working my way down to it. Right now I'm doing the Graph Element.
Sweet, thank you sir!
Oh wow, if you solved the "spastic headers" problem, that will get in there quick.
I'm surprised you can't create an empty table. One thing you can do is literally create the table with 1 row of "empty" data. Then use
Updateto change the table later.My "problem" with additions to features is the porting effort to span them across the other 3 ports so that the SDK remains portable. I already know a number of features need cross-porting.
I don't think I'm communicating the message correctly regarding changes to PySimpleGUI.....
My suggestions have been attempts to get you to create solutions that do not involve modifying any PySimpleGUI.py code on your part, but instead make the SAME CALLS inside YOUR code. In other words, if you can change Update to make this work, then you can do the same operation inside YOUR code rather than calling Update.
I'll drop the bug fix in the next release. I haven't looked at it yet. Thanks for pointing it out.
Sorry for leading you on a wild goose chase about the supposed typo that wasn't a typo. I think the main cause for my spastic column headers problem was actually due to the fact that I was setting all headers to initially be the same text string (A list of strings that has the same string for each value of the list). Apparently, tk Tables don't like this and really expects you to have unique column header names. As long as I give my "empty" table (empty values) some unique default headers, everything behaves nicely. I'm putting this additional info here more for others to read and benefit than for you to "fix" it.
BR,
Jason
hi, trying to use the Update code to make changes to my table headings.. cant see to make it work? could anybody please show me how it works..
It's still an open enhancement. The changes have not been made to the code.
hi, sorry I wasn't clear, I meant the changes that user jbiz25 made to the Update code.