ragardner / tksheet

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

Deleting Row(s): TypeError: cannot pickle '_tkinter.tkapp' object #241

Closed spettitt9095 closed 2 months ago

spettitt9095 commented 2 months ago

Hello, apologies I'm quite new to Python so this may be user error.

I have an application where I need to add or remove rows from a sheet (rows of checkboxes in banks of 6, but that's probably not relevant here).

I can add them easily: self.sheet.insert_rows(rows = 6). But if I need to delete them, I get TypeError: cannot pickle '_tkinter.tkapp' object. I'm using CustomTkinter but can reproduce the same with normal Tkinter.

I've tried del_row and del_rows but both produce the error.

I made a simple reproducible example based one of the tksheet examples. Is there a way to make this work please?

Thank you.

`from tksheet import (Sheet, num2alpha as n2a,) import tkinter as tk

class demo(tk.Tk): def init(self): tk.Tk.init(self)

    self.frame = tk.Frame(self, width = 700, height = 700)

    self.data = [
        ["3", "c", "z"],
        ["1", "a", "x"],
        ["1", "b", "y"],
        ["2", "b", "y"],
        ["2", "c", "z"],
    ]
    self.sheet = Sheet(
        self.frame,
        data=self.data,
        column_width=180,
        theme="dark",
        height=700,
        width=500,
    )
    self.sheet.enable_bindings(
        "copy",
        "rc_select",
        "arrowkeys",
        "double_click_column_resize",
        "column_width_resize",
        "column_select",
        "row_select",
        "drag_select",
        "single_select",
        "select_all",
    )
    self.frame.grid(row=0, column=0)

    self.sheet.grid(row=1, column=0)

    self.button = tk.Button(self.frame, command=self.delete_sheet, text = 'delete some rows')
    self.button.grid(row = 0, column=0)

    self.sheet.dropdown(
        self.sheet.span(n2a(0), header=True, table=False),
        values=["All", "1", "2", "3"],
        set_value="All",
        selection_function=self.header_dropdown_selected,
        text="Header A Name",
    )
    self.sheet.dropdown(
        self.sheet.span(n2a(1), header=True, table=False),
        values=["All", "a", "b", "c"],
        set_value="All",
        selection_function=self.header_dropdown_selected,
        text="Header B Name",
    )
    self.sheet.dropdown(
        self.sheet.span(n2a(2), header=True, table=False),
        values=["All", "x", "y", "z"],
        set_value="All",
        selection_function=self.header_dropdown_selected,
        text="Header C Name",
    )

def header_dropdown_selected(self, event=None):
    hdrs = self.sheet.headers()
    # this function is run before header cell data is set by dropdown selection
    # so we have to get the new value from the event
    hdrs[event.loc] = event.value
    if all(dd == "All" for dd in hdrs):
        self.sheet.display_rows("All")
    else:
        rows = [
            rn for rn, row in enumerate(self.data) if all(row[c] == e or e == "All" for c, e in enumerate(hdrs))
        ]
        self.sheet.display_rows(rows=rows, all_displayed=False)
    self.sheet.redraw()

def delete_sheet(self):
    self.sheet.del_rows(rows = 2)

app = demo() app.mainloop()`

spettitt9095 commented 2 months ago

I think I might have figured this out - I think I need to remove the checkboxes before I try and delete the rows. Testing at the moment.

spettitt9095 commented 2 months ago

I think this is my bad - I was looping over rows and columns to add checkboxes, rather than providing a span range. Seems to be working now.

ragardner commented 1 month ago

Thanks for your report, sorry for the late reply,

If you have anymore issues let me know

I am not 100% sure but such an error may have been an issue in an older version where in order to undo a change some sheet information is pickled and the pickled information wrongly contained references to tkinter objects which cannot be pickled.