Home > other >  How to program follow-up actions when the state of a ttk.Checkbutton widget changes?
How to program follow-up actions when the state of a ttk.Checkbutton widget changes?

Time:11-12

I noticed a behaviour in the ttk.Checkbuttons widget. That is, any applied bindings or event handlers to this widget always occurs before the widget's command option method/function is executed.

Significance:

  1. Given that the change in the state of the ttk.Checkbuttons is performed by the command option method/function, the value of the ttk.Checkbuttons['variable'] accessed through an event handler will always be of the old state and not the new state that is defined by the widget's command option method/function.

  2. Changing the value of ttk.Checkbuttons['variable'] in an event handler will mess up the performance of the widget's command option method/function. Hence, ttk.Checkbuttons['variable'] should be set in the widget's command option method/function.

Question:

Given the above, so what is the purpose of binding event handlers to a ttk.Checkbuttons widget?

Event handlers are executed when an event occurs, e.g. when <ButtonRelease-1> has occurred at the ttk.Checkbutton widget. If I want to design a follow-up action based on the state of the widget, I can't do that via event handler as the widget instate has not been updated yet. A workaround is to assume the widget instate and variable obtained in an event handler is the opposite of the reported instate or variable.get() values. However, such an approach seems presumptuous.

How do should I use event handlers for a ttk.Checkbutton to program follow-up actions when there is a state change? Or should I not use it and only use the widgets command option method/function to design a follow-up action based on the state of the widget?

CodePudding user response:

Given the above, so what is the purpose of binding event handlers to a ttk.Checkbuttons widget?

So that you can define your own behavior that overrides the default behavior.

How do should I use event handlers for a ttk.Checkbutton to program follow-up actions when there is a state change?

One solution is to not use event handlers. Instead, set a trace on the associated variable. With a variable trace, your callback function will be called after the variable has been set, and will be called every time the value changes even when the change is done by something other than an event.

cb_var = tk.StringVar(value="off")
cb = ttk.Checkbutton(root, variable=cb_var, onvalue="on", offvalue="off", text="Ready?")
cb_var.trace_add('write', callback)

Another solution is to create a custom binding tag that comes after the binding tag of the class.

Example:

cb_var = tk.StringVar(value="off")
cb = ttk.Checkbutton(root, variable=cb_var, onvalue="on", offvalue="off", text="Ready?")
tag = f'custom_{cb}'
cb.bindtags((cb, 'TCheckbutton', '.', tag, 'all'))
cb.bind_class(tag, "<ButtonRelease-1>", callback)

With the above, the callback will be called on the <ButtonRelease-1> button after that event has been processed by the default binding on the widget class. If you do this, you should also add a binding to the spacebar in a similar fashion since you can also set the value of a checkbutton with the spacebar.

For another example of bindtags with a bit more of a discussion about how they work, see this answer to the question How to bind self events in Tkinter Text widget after it will binded by Text widget?. Also, see this answer to the question Basic query regarding bindtags in tkinter.

  • Related