P bertJoha
P bertJoha

Reputation: 96

Tkinter Checkbutton appearance not updating until mouse leaves button's area

I want to change a TKinter.Checkbutton's value when it is being clicked.

The button is a Checkbutton and I use an IntVar to track/change its value.

In the following example I just have one button and I want it to change state back to 0 whenever we click on it (it can sound stupid in this case but I am trying to solve an other more complex case where more buttons change values).

The value is actually updated but the button's appearance does not change until the mouse leaves what seems to be the button's area.

Here is the minimal example :

try :
    import Tkinter as tk
except ImportError as e:
    import tkinter as tk

root = tk.Tk()
val = tk.IntVar(root)
val.trace("w", lambda a, b, c: val.set(0))
button = tk.Checkbutton(root, text="button", variable=val)
button.pack()

root.mainloop()

To reproduce :

Why does it wait for the mouse to leave its area ? How could I force the button's appearance to change instantly ?

Thanks

EDIT :

It looks like using ttk.Checkbutton does not have this issue. Still it does not explain why the original button behave like it does and how to have the desired behaviour with tk buttons.

Upvotes: 0

Views: 359

Answers (1)

jasonharper
jasonharper

Reputation: 9621

Setting a variable from within a write trace on the same variable is extremely problematic - this would be an infinite recursion, if Tcl didn't automatically disable traces during the execution of a trace. The widget's updating of its displayed value is itself handled by a trace on the variable, so it's not surprising that the display gets out of sync - what's surprising is that it gets back into sync later, I have no idea how that happens.

If you must do this from a write trace (rather than the command= option as has been suggested, which happens when the variable is in a more stable state), you need to defer the change slightly: root.after(1, var.set, 0) perhaps.

Upvotes: 1

Related Questions