ragardner / tksheet

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

KeyError when binding a function (which selects a row) to "cell_select" #226

Closed hans-fritz-pommes closed 4 months ago

hans-fritz-pommes commented 4 months ago

I am using tksheet version 7.1.21, and it works great, but I get one Error every time, which doesn't really disturb the programme, but is very annoying. This is my code which causes the error:

import tkinter as tk
import tksheet
top = tk.Tk()
sheet = tksheet.Sheet(top)
sheet.grid()
sheet.set_sheet_data([[f"{ri+cj}" for cj in range(4)] for ri in range(4)])
sheet.enable_bindings()
## this produces the error
def clicked_on_cell(event):
    sheet.select_row(event.selected.row,redraw=False,run_binding_func=False)
    sheet.add_cell_selection(event.selected.row,event.selected.column,redraw=False,run_binding_func=False)
sheet.extra_bindings("cell_select",clicked_on_cell)
## end
top.mainloop()

When I click on a cell the second time, I get this Error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\HansFritzPommes\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\HansFritzPommes\AppData\Local\Programs\Python\Python312\Lib\site-packages\tksheet\main_table.py", line 3017, in b1_release
    self.hide_selection_box(self.being_drawn_item)
  File "C:\Users\HansFritzPommes\AppData\Local\Programs\Python\Python312\Lib\site-packages\tksheet\main_table.py", line 5853, in hide_selection_box
    box = self.selection_boxes.pop(item)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 19

I get another annoying error (in the same function b1_release) with this code when I click on a region without cells:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\HansFritzPommes\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\HansFritzPommes\AppData\Local\Programs\Python\Python312\Lib\site-packages\tksheet\main_table.py", line 3016, in b1_release
    r_to_sel, c_to_sel = self.selected.row, self.selected.column
                         ^^^^^^^^^^^^^^^^^
AttributeError: 'tuple' object has no attribute 'row'

Could you solve these problems officially? Per example with the following code: In main_table.py: In class MainTable: In function b1_release:

def b1_release(self, event=None):
        if self.being_drawn_item is not None:
            to_sel = self.coords_and_type(self.being_drawn_item)
            try: ### change this
                r_to_sel, c_to_sel = self.selected.row, self.selected.column
            except AttributeError: ### and change this
                return ### and change this
            try: ### and change this
                self.hide_selection_box(self.being_drawn_item)
            except KeyError: ### and change this
                return ### and change this
            self.being_drawn_item = None
            self.set_currently_selected(
                r_to_sel,
                c_to_sel,
                item=self.create_selection_box(
                    *to_sel,
                    state=(
                        "hidden"
                        if (to_sel.upto_r - to_sel.from_r == 1 and to_sel.upto_c - to_sel.from_c == 1)
                        else "normal"
                    ),
                    set_current=False,
                ),
            )

It would be great, thank you for your time, ragardner.

ragardner commented 4 months ago

Hello,

Thanks for your report and suggestions,

I agree that these errors needed addressing and made some changes in 7.2.0

Your code should run without errors now but let me know if you have further issues

Release notes:

Version 7.2.0

Fixed:

Changed:

Edit: There was a slight regression in 7.2.0 which is fixed in 7.2.1, this newer version also has a bugfix for selection box borders not showing up when selection functions are called from Sheet() while the sheet is in the process of selecting

hans-fritz-pommes commented 4 months ago

Hello ragardner, yes, thank you for the fast help, the code now works correctly, without errors, but it seems there is another problem:

I tested it with version 7.2.0, where I unfortunately discovered, that the index numbers don't get the same colors when they are selected by a click like when they are selected by a command. This is bad in theme "light green", because the numbers' color is green and doesn't change when I select the row via command -> the user cannot read the number, because it's "green on green". You can reproduce this with the code I sent above and sheet.change_theme("light green"). I don't know yet, if the bug is fixed in 7.2.1, but I'll let you know as soon as I checked. Thank you for your attention!

PS: I'm new to GitHub: Should I close this issue and open a new one for the colors? Because the main problem of this issue is fixed now...

hans-fritz-pommes commented 4 months ago

(The color problem was existing before, too, but there the index' color wasn't the same as the numbers'.)

hans-fritz-pommes commented 4 months ago

Now I checked: The color problem is existing in 7.2.1 too.

PS: I saw the change with the cell borders: Great, thank you.

Attachements: Row selected via click: row_selected_via_click

Row selected via command: row_selected_via_command

ragardner commented 4 months ago

Hello,

Sorry about the color issue and thanks for alerting me

Don't worry about creating a new issue

I will have to fix this tomorrow though sorry, will update when I have

hans-fritz-pommes commented 4 months ago

No pressure

ragardner commented 4 months ago

Hello,

I think this color issue occurs because selections need a redraw in order to update the colors

If you change your redraw arguments to redraw=True it should fix it, let me know if this doesn't work for you though

There isn't currently code to update just the canvas items involved in a selection, I am currently not sure if it's worth changing

Nearly all of the functions in Sheet() which have a redraw parameter will only redraw once after the code has finished running and tkinter updates

There are some cases where it might redraw a few times but even if you have 100 functions with the keyword argument redraw=True one after the other it should only redraw a few times max afterwards

hans-fritz-pommes commented 4 months ago

Thank you very much: That works!