ragardner / tksheet

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

sheet lagging behind #170

Open ywith opened 1 year ago

ywith commented 1 year ago

I have a sheet with 3 columns. Column 1 and 2 you enter data and column 3 is locked and does a calculation off the other two. However, with the latest release of python 3.11.3 and windows 11 entering any value in the column. I downgraded with #pip install tksheet==5.4.1 to show the values, but even with this the calculation seems to be 1 behind. I type 1 and 2 and not until i go back into 1 or 2 does column 3 update with the correct value

ragardner commented 1 year ago

So the issue is also present with tksheet version 6.0.1? Is there any way you could give me a bit of example code? it's hard to track down the issue without it

ywith commented 1 year ago

Hi, so its basically for storing numerical data and doing some validation...I have some validation on the parent class... self.sheet.extra_bindings("end_edit_cell", func=self.OkChange) to run okChange. If i remove ok change the value updates. The issue is since we bought a new PC that came with windows 11. Code without the additional line works on windows 10, but as a workaround i have just forced saving back the value to the cell at the end on latest version of python and your programme.

so def OkChange(self, event=None): Row = event[0] Col = event[1] self.sheet.highlight_rows([Row], bg=None)

    self.currentVal = str(event[3])
    self.zippedData[Row][Col] = self.currentVal   #########adding this line seems to fix it by saving the value back to the data if that makes sense. However on windows 10 it worked fine. 
    self.CheckValidValues(Row, Col)
    if self.validValue == False:
        self.sheet.highlight_cells(row=Row, column=Col, bg="Red")
    elif self.validRow == False:
        self.sheet.highlight_rows([Row], bg="Red")
    elif self.validRow == True:
        self.sheet.highlight_rows([Row], bg="Green")
    else:
        self.sheet.highlight_cells(row=Row, column=Col, bg="Green")

......

here is the parent class...def createLabelAndInputs(self):

    self.sheet.set_sheet_data(self.zippedData)
    self.sheet.readonly_columns(columns=[0], readonly=True, redraw=True)  # make LN column read only
    self.sheet.readonly_rows(rows=[0], readonly=True, redraw=True)  # make titles none editable
    self.sheet.highlight_columns(columns=[0], bg="blue", fg="white")  # make LN column blue and white
    self.sheet.highlight_rows(rows=[0], bg="blue", fg="white")
    self.sheet.align(align="center", redraw=True)

    self.sheet.grid()
    self.sheet.height_and_width(self.screenheight, self.screenwidth)
    # self.sheet.enable_bindings("all")

    self.sheet.enable_bindings(("single_select",

                                "row_select",

                                "column_width_resize",

                                "arrowkeys",

                                "right_click_popup_menu",

                                "rc_select",

                                "rc_insert_row",

                                "rc_delete_row",

                                "copy",

                                "cut",

                                "paste",

                                "delete",

                                "undo",

                                "edit_cell",

                                "end_edit_cell"))

    self.sheet.extra_bindings("end_edit_cell", func=self.OkChange)

    self.DT.mainloop()
ragardner commented 1 year ago

@ywith Thanks for the extra info, I think I have tracked down the issue. I am sorry to report that it is because of a change I made to a newer version of tksheet, I have not checked to see which version sorry but I will if you want me to

Basically since the change by default using extra_bindings with "end_edit_cell" or "edit_cell" means whichever function you bind to it has to return the text you want to update the cell with, if it returns None then the cell isn't updated

You have two choices to resolve this, you can either:

Let me know if these fix your issue, if it does I am sorry for the inconvenience, I am thinking that I should have made it clearer that the change was made, or I should have not made it the default behavior

ywith commented 1 year ago

Hi, i added return event.text and it now crashes. what line do i change to make the behaviour how it used to be, as i just typed one result in of 32.5, it showed 3.5 and then the next result shows none and then crashes

ragardner commented 1 year ago

Hm, sorry about that, it should work with the latest version but if you want to keep your current version you could try either

  • Use the argument edit_cell_validation = False in your = Sheet(... initialization or you can do the same with sheet.set_options(edit_cell_validation = False), with the set_options() function you only have to do this once, so you can put it near your sheet initialization code

Or try using return event[3] or whichever index it looks like the cell value is in, use print (event) to see if you can find it

ywith commented 1 year ago

this is a child one.... def OkChange(self, event=None): Row = event[0] Col = event[1] self.sheet.highlight_rows([Row], bg=None)

    self.currentVal = str(event[3])
    self.zippedData[Row][Col] = self.currentVal   #tried with this commented out and not commented out
    self.ABCCheck(Row, Col)
    if self.validValue == False:
        self.sheet.highlight_cells(row=Row, column=Col, bg="Red")
    elif self.validRow == False:
        self.sheet.highlight_rows([Row], bg="Red")
    elif self.validRow == True:
        self.sheet.highlight_rows([Row], bg="Green")
    else:
        self.sheet.highlight_cells(row=Row, column=Col, bg="Green")

    if Col == 1 or Col == 2:
        self.calcDensity(Row)

    #return self.currentVal  #tried with this commented out and not commented out
     #tried event.text #tried with this commented out and not commented out
ragardner commented 1 year ago

this is a child one.... def OkChange(self, event=None): Row = event[0] Col = event[1] self.sheet.highlight_rows([Row], bg=None)

    self.currentVal = str(event[3])
    self.zippedData[Row][Col] = self.currentVal   #tried with this commented out and not commented out
    self.ABCCheck(Row, Col)
    if self.validValue == False:
        self.sheet.highlight_cells(row=Row, column=Col, bg="Red")
    elif self.validRow == False:
        self.sheet.highlight_rows([Row], bg="Red")
    elif self.validRow == True:
        self.sheet.highlight_rows([Row], bg="Green")
    else:
        self.sheet.highlight_cells(row=Row, column=Col, bg="Green")

    if Col == 1 or Col == 2:
        self.calcDensity(Row)

    #return self.currentVal  #tried with this commented out and not commented out
     #tried event.text #tried with this commented out and not commented out

Ah, if you have already tried it then I'm not sure what's going on, do you happen to know what the error is?

ywith commented 1 year ago

i have downgraded and then kept that code of self.zippedData[Row][Col] = self.currentVal and it seems to work.

ragardner commented 1 year ago

Hm... if you want, I could maybe debug it myself if your complete program source code isn't sensitive, you can attach files to messages here I think

ywith commented 1 year ago

Hi, it does have quite a bit of sensitive stuff in it. I have downgraded as mentioned, and am picking and choosing the child "okchanges" how they operate on a case by case basis. I have already had about 10 calls this morning saying various ones don't work, so I'm just changing each usecase of the class hardcoded. Generally the manually pulling event 3 and setting it as the value and returning together seem to be working so far. However, on some the returning has crashed it so i have just commented out the ones the return crashes it. I could do a teams or something like that to share the screen if you want to look, but I couldn't do a paste of the code as it has proprietary methods for the company in it.

ragardner commented 1 year ago

I'm really sorry about the trouble you're having,

I think possibly the safest thing might be to not use return at all and just use set_cell_data(row, column, value) to manually set the value, this would be inside okchanges

With version 5.4.1:

ragardner commented 1 year ago

@ywith Ok sorry, I made some edits to my last comment specifically if you're using 5.4.1 which might help

I'm really sorry about the trouble you're having,

I think possibly the safest thing might be to not use return at all and just use set_cell_data(row, column, value) to manually set the value, this would be inside okchanges

With version 5.4.1:

If you don't want the value to be converted to a string use set_cell_data(row, column, value, set_copy = False) You could alternatively use self.sheet.MT.data_ref[row][column] = value for an even more direct approach

ragardner commented 1 year ago

For forwards compatibility you could use this instead:

try:
    self.sheet.MT.data_ref[row][column] = self.currentVal
except:
    self.sheet.MT.data[row][column] = self.currentVal
ywith commented 1 year ago

Hi thanks. The staff should start using the program again after lunch today. I will let you know if there are further issues.