diff --git a/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py b/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py new file mode 100644 index 00000000..01fa231a --- /dev/null +++ b/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +import PySimpleGUI as sg +import random +import string +import operator + +""" + Table Element Demo With Sorting + + The data for the table is assumed to have HEADERS across the first row. + This is often the case for CSV files or spreadsheets + + In release 4.48.0 a new enable_click_events parameter was added to the Table Element + This enables you to click on Column Headers and individual cells as well as the standard Row selection + + This demo shows how you can use these click events to sort your table by columns + +""" + +sg.theme('Light green 6') +# ------ Some functions to help generate data for the table ------ +def word(): + return ''.join(random.choice(string.ascii_lowercase) for i in range(10)) +def number(max_val=1000): + return random.randint(0, max_val) + +def make_table(num_rows, num_cols): + data = [[j for j in range(num_cols)] for i in range(num_rows)] + data[0] = [word() for __ in range(num_cols)] + for i in range(1, num_rows): + data[i] = [i, word(), *[number() for i in range(num_cols - 1)]] + return data + +# ------ Make the Table Data ------ +data = make_table(num_rows=15, num_cols=6) +# headings = [str(data[0][x])+' ..' for x in range(len(data[0]))] +headings = [f'Col {col}' for col in range(len(data[0]))] + +def sort_table(table, cols): + """ sort a table by multiple columns + table: a list of lists (or tuple of tuples) where each inner list + represents a row + cols: a list (or tuple) specifying the column numbers to sort by + e.g. (1,0) would sort by column 1, then by column 0 + """ + for col in reversed(cols): + try: + table = sorted(table, key=operator.itemgetter(col)) + except Exception as e: + sg.popup_error('Error in sort_table', 'Exception in sort_table', e) + return table + +# ------ Window Layout ------ +layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, + auto_size_columns=True, + display_row_numbers=True, + justification='right', + num_rows=20, + alternating_row_color='lightyellow', + key='-TABLE-', + selected_row_colors='red on yellow', + enable_events=True, + expand_x=True, + expand_y=True, + enable_click_events=True, # Comment out to not enable header and other clicks + tooltip='This is a table')], + [sg.Button('Read'), sg.Button('Double'), sg.Button('Change Colors')], + [sg.Text('Cell clicked:'), sg.T(k='-CLICKED-')], + [sg.Text('Read = read which rows are selected')], + [sg.Text('Double = double the amount of data in the table')], + [sg.Text('Change Colors = Changes the colors of rows 8 and 9'), sg.Sizegrip()]] + +# ------ Create Window ------ +window = sg.Window('The Table Element', layout, + ttk_theme='clam', + resizable=True) + +# ------ Event Loop ------ +while True: + event, values = window.read() + print(event, values) + if event == sg.WIN_CLOSED: + break + if event == 'Double': + for i in range(1, len(data)): + data.append(data[i]) + window['-TABLE-'].update(values=data[1:][:]) + elif event == 'Change Colors': + window['-TABLE-'].update(row_colors=((8, 'white', 'red'), (9, 'green'))) + if isinstance(event, tuple): + # TABLE CLICKED Event has value in format ('-TABLE=', '+CLICKED+', (row,col)) + if event[0] == '-TABLE-': + if event[2][0] == -1 and event[2][1] != -1: # Header was clicked and wasn't the "row" column + col_num_clicked = event[2][1] + new_table = sort_table(data[1:][:],(col_num_clicked, 0)) + window['-TABLE-'].update(new_table) + data = [data[0]] + new_table + window['-CLICKED-'].update(f'{event[2][0]},{event[2][1]}') +window.close() diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 65cc10f4..775a2df1 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -version = __version__ = "4.49.0.7 Unreleased" +version = __version__ = "4.49.0.8 Unreleased" _change_log = """ @@ -22,6 +22,9 @@ _change_log = """ 4.49.0.7 Addition of Window.get_size_accurate - size based on the geometry string Removed window move of the theme color swatch preview window. Seems to center correctly now. + 4.49.0.8 + Added check for a bad value being returned from tkinter during the table clicked event + Removed print when patch of 8.6.9 ttk treeview code is patched """ __version__ = version.split()[0] # For PEP 396 and PEP 345 @@ -7792,11 +7795,15 @@ class Table(Element): row = None else: row = None - column = int(self.Widget.identify_column(event.x)[1:])-1-int(self.DisplayRowNumbers is True) + col_identified = self.Widget.identify_column(event.x) + if col_identified: # Sometimes tkinter returns a value of '' which would cause an error if cast to an int + column = int(self.Widget.identify_column(event.x)[1:])-1-int(self.DisplayRowNumbers is True) + else: + column = None except Exception as e: - warnings.warn('Error getting table click data for table with key='.format(self.Key), UserWarning) + warnings.warn('Error getting table click data for table with key= {}\nError: {}'.format(self.Key, e), UserWarning) if not SUPPRESS_ERROR_POPUPS: - _error_popup_with_traceback('Unable to complete operation getting the clicked event for table with key {}'.format(self.Key), _create_error_message()) + _error_popup_with_traceback('Unable to complete operation getting the clicked event for table with key {}'.format(self.Key), _create_error_message(), e, 'Event data:', obj_to_string_single_obj(event)) row = column = None self.last_clicked_position = (row, column) @@ -14734,7 +14741,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): _add_right_click_menu(element) if tclversion_detailed == '8.6.9' and ENABLE_TREEVIEW_869_PATCH: - print('*** tk version 8.6.9 detected.... patching ttk treeview code ***') + # print('*** tk version 8.6.9 detected.... patching ttk treeview code ***') table_style.map(style_name, foreground=_fixed_map(table_style, style_name, 'foreground', element.SelectedRowColors), background=_fixed_map(table_style, style_name, 'background', element.SelectedRowColors)) @@ -14854,7 +14861,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): _add_right_click_menu(element) if tclversion_detailed == '8.6.9' and ENABLE_TREEVIEW_869_PATCH: - print('*** tk version 8.6.9 detected.... patching ttk treeview code ***') + # print('*** tk version 8.6.9 detected.... patching ttk treeview code ***') tree_style.map(style_name, foreground=_fixed_map(tree_style, style_name, 'foreground', element.SelectedRowColors), background=_fixed_map(tree_style, style_name, 'background', element.SelectedRowColors))