ragardner / tksheet

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

Bug on delete row action #253

Closed skedus closed 1 week ago

skedus commented 2 weeks ago

Hi, I found a bug on the delete row binding of tksheet It seems that delete_row action in the right clic fail if a checkbox exist in the row. I tried to isolate the problem with the following simple code:

Error message

  File "tksheet/main_table.py", line 4903, in rc_delete_rows
    event_data = self.delete_rows_data(data_rows, event_data)
  File "tksheet/main_table.py", line 4859, in delete_rows_data
    event_data["options"] = self.pickle_options()
  File "tksheet/main_table.py", line 4779, in pickle_options
    return pickle_obj(
AttributeError: Can't pickle local object 'demo.__init__.<locals>.<lambda>'

Example code:

I added checkbox in the column 1

from tksheet import Sheet
import tkinter as tk

class demo(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)
        self.frame = tk.Frame(self)
        self.frame.grid_columnconfigure(0, weight=1)
        self.frame.grid_rowconfigure(0, weight=1)

        self.sheet = Sheet(
            self.frame,
            data=[[f"Row {r}, Column {c}" for c in range(6)] for r in range(21)],
            column_width=180,
            height=700,
            width=1100,
        )
        self.sheet.enable_bindings(
            "edit_cell",
            "rc_insert_row",
            "rc_delete_row",
            "rc_select",
            "arrowkeys",
            "column_width_resize",
            "row_select",
            "single_select",
        )

        # Added checkbox
        for row in range(self.sheet.get_total_rows()):
            self.sheet.create_checkbox(
                r=row,
                c=1,
                checked=False,
                check_function=lambda event=None: self.click_checkbox(event),
            )

        self.frame.grid(row=0, column=0, sticky="nswe")
        self.sheet.grid(row=0, column=0, sticky="nswe")

    def click_checkbox(self, event):
        """Custom checkbox"""
        print(f"event={event}")

app = demo()
app.mainloop()
ragardner commented 2 weeks ago

Hello, thanks very much for discovering this and pointing it out

My apologies, this one was a bit of a stupid oversight

I have addressed it in version 7.2.21 by removing pickle from the event data stuff. If a pickled function belonged to a tkinter object then an error was generated. Tkinter stuff really doesn't want to be pickled.

The only things that are pickled now are named spans which do not contain functions and are stripped of the tkinter object before pickling

I have tested the new solution and it seems to work just fine with named spans, tags, highlights, check boxes etc. and undo/redo

skedus commented 2 weeks ago

Tested this is working fine :-) I'm migrating my application from many tksheet v5 to tksheet v7 I really appreciate your quick support Once again thank you very much :-)