ragardner / tksheet

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

BUG: Checkbox "check_function" executes function on table creation but not when actually clicking the checkbox #149

Closed Archern4r closed 1 year ago

Archern4r commented 1 year ago

Hi there,

when implementing checkboxes in tksheet I encountered it tries to execute the function stated in the "check_function"-keyword upon drawing the table but not when actually clicking the checkbox. I tried a few things to circumvent this but ultimately, this seems to be a bug to me.

For recreation, I included an example of how I encountered the bug. It's pretty ugly but it should do the trick. I use python 3.11, tksheet 5.5.0.

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

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

        self.table_frame = ctk.CTkFrame(self)
        self.table_frame.grid(row=2, column=0, columnspan=2, padx=5, pady=5, sticky="nsew")

        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!", "Checkbox"],
                                 empty_horizontal=0)
        self.table_sheet.enable_bindings()
        self.table_sheet.grid(row=0, column=0, sticky="nsew")

        self.send_button = ctk.CTkButton(self, text="Click me!", command=self.clicking_button_action)
        self.send_button.grid(row=0, column=1, pady=2, padx=2, sticky="we")

    def clicking_button_action(self):

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

        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!", check_function=self.checkbox_clicking())
        # will execute the checkbox_clicking_function when drawing the table but never when clicking the button.
        self.table_sheet.set_all_cell_sizes_to_text(redraw=True)

    def checkbox_clicking(self):
        messagebox.showinfo("Info", "Checkbox clicked!")

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

Hello, I am not sure if this is the problem but try using check_function=self.checkbox_clicking)

in other words remove the brackets from self.checkbox_clicking

CalJaDav commented 1 year ago

Two things:

1.) As Ragardener mentioned you need to pass the function object to the check_function param, by putting the brackets on it you are instantiating the function and passing the return value to it instead. i.e., change: check_function=self.checkbox_clicking() to check_function=self.checkbox_clicking

2.) The checkbutton will try to parse some information about the button that has been clicked, the value and the row/column index to the argument. This will cause an error because your function only takes one arguement. Try changing it to... def checkbox_clicking(self, data): messagebox.showinfo("Info", f"row: {data[0]}, col: {data[1]}, event: {data[2]}, value: {data[3]}") ... so that you can see what this data looks like.

In summary, there is no bug here. I think this issue can be closed @ragardner

Archern4r commented 1 year ago

Alright, thank you both very much. A rather easy solve for my problem.

I would suggest to include the point by CalJaDav into the documentation though, as without his 2nd point I would have been doomed to trial and error I guess.

Thanks for the help and thanks for the library.

ragardner commented 1 year ago

I agree about the documentation, thanks will update @Archern4r