ragardner / tksheet

Python tkinter table widget for displaying tabular data
https://pypi.org/project/tksheet/
MIT License
404 stars 50 forks source link

Redrawing tables with checkboxes in them will fail if checkboxes are in the last column and all columns are on display. #152

Closed Archern4r closed 1 year ago

Archern4r commented 1 year ago

Hi there,

another error came up lately and I think this is actually a bug instead of just user error(by me): If one draws a table and creates a checkbox in the last column, then redraws the table (doesn't really matter if new data or not), an error will be thrown (IndexError: list index out of range), but only when all columns are on display (at least for me).

It seems to me that the problem arises in _tksheet_main_table.py in line 4148-4152 (although I might be wrong on that), because of the error only occuring when I resize the table to show all columns. The error is actually caused by line 4206.

When I tried debugging a bit myself I found it tries to redraw the table using the original data only (without the checkbox column) and then inserting the checkbox column afterwards. This means if in the code example the checkbox column is set to 0 instead of at the end, the data is first set to the input data and then the checkbox column can be inserted correctly, its index not being out of bound.

I tried to circumvent the problem by first deleting all data in the sheet by iterating over the rows in the sheet and deleting them one-by-one EDIT: and after fixing an coding error by me, that helps as a workaround. Example code:

import customtkinter as ctk
import pandas as pd
from tksheet import Sheet

class start_gui(ctk.CTk):
    def __init__(self):
        super().__init__()

        self.table_frame = ctk.CTkFrame(self)
        self.table_frame.pack(expand=True, fill="both")

        self.table_sheet = Sheet(self.table_frame, show_top_left=False, show_row_index=False,
                                 expand_sheet_if_paste_too_big=True,
                                 headers=["Much much data", "A lot less data", "This is awesome data!",
                                          "some more data", "in order to stretch", "the window", "Checkbox"],
                                 empty_horizontal=0)
        self.table_sheet.enable_bindings()
        self.table_sheet.pack(expand=True, fill="both")

        self.send_button = ctk.CTkButton(self, text="Click me!", command=self.clicking_button_action)
        self.send_button.pack()

    def clicking_button_action(self):

        self.sheet_data = pd.DataFrame({"Foo":[1, 2, 3], "Bar": ["blah", "blah", "blah"], "Baz":["whop", "da", "doo"],
                                        "bla":[1, 2, 3], "blaa":[1, 2, 3], "blargh":[1, 2, 3]})

        self.sheet_data = self.sheet_data.values.tolist()
        self.table_sheet.set_sheet_data(self.sheet_data)
        self.columnlength = len(self.table_sheet.get_sheet_data()[0])
        self.checkbox_col = self.columnlength
        self.table_sheet.create_checkbox(r="all", c=self.checkbox_col, checked=True,
                                         text="Click me too!")
        self.table_sheet.set_all_cell_sizes_to_text(redraw=True)

tkinter_test = start_gui()
tkinter_test.mainloop()
ragardner commented 1 year ago

Thanks very much for all the testing and help, I’ll get round to this soon

ragardner commented 1 year ago

Hello,

When I recreated your code on my pc using version 5.6.0 I couldn't get an error to occur, I might have fixed an issue present in an older version, could you try with the latest version sorry

Archern4r commented 1 year ago

Hi there,

sorry for late reply. The problem persists for me on 5.6.2 using the same code as in my example above.

Remember the error will only occur when all columns are shown, not if not all are on display. The error can then even be fixed by resizing the window so that not all columns are displayed and clicking the button again.

ragardner commented 1 year ago

Hello, I finally managed to recreate the issue after using your sheet data, it is fixed in 5.6.5

The issue resulted because the main table was attempting to redraw a checkbox from the previous go round (as they weren't deleted with set_sheet_data()) and the row length was too short to do so

I've put in a try and except in redrawing checkboxes, if there's no associated data they will be unchecked until the user checks them at which point the row will be extended if necessary and the data will exist