Search code examples
python-3.xtkintercallbackwidget

Python/tkinter - change entry status via checkbox


I want to activate the second entry when the checkbox is checked...but the it works the other way around. What am I doing wrong? Based on another question I have posted it seems the event "<ButtonRelease>" occurs before the bonding. Why is that? Can I use "command" in the checkbox instaed?

import tkinter as tk

def set_entry_status(event, var, widg):
    print(var.get())
    if var.get():
        widg[-1]['state'] = 'normal'
    else:
        widg[-1]['state'] = 'disabled'

def CustomWidget(frame, name, unit, ):
    var_e = []
    widget_e = []

    var_c = tk.IntVar(master=frame, value=0)
    widget_c = tk.Checkbutton(master=frame, text='', variable=var_c)
    widget_c.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="ns")

    label_l = name + " (" + unit + ")"  # nome + unità di misura in parentesi per GUI
    widget_l = tk.Label(frame, text=label_l, padx=1, pady=1)
    widget_l.grid(row=0, column=1, columnspan=1, padx=5, pady=5, sticky="wns")

    var_e.append(tk.StringVar(master=frame, value='A'))
    widget_e.append(tk.Entry(frame, textvariable=var_e[-1], width=10, state="normal"))  
    widget_e[-1].grid(row=0, column=2, columnspan=1, padx=5, pady=5, sticky="ns")

    var_e.append(tk.StringVar(master=frame, value='B'))
    widget_e.append(tk.Entry(frame, textvariable=var_e[-1], width=10, state="normal"))  
    widget_e[-1].grid(row=0, column=3, columnspan=1, padx=5, pady=5, sticky="ns")

    # set initial entry state
    if var_c.get():
        widget_e[-1]['state'] = 'normal'
    else:
        widget_e[-1]['state'] = 'disabled'

    # checkbox - binding
    widget_c.bind("<ButtonRelease>", lambda event: set_entry_status(event, var_c, widget_e))

root = tk.Tk()
root.title('My Window')
CustomWidget(root, 'name', 'unit')
root.mainloop()

Solution

  • Indeed you can use command kwarg like I suggested in my other answer. In that case event must be removed from the arguments of your callback function:

    import tkinter as tk
    
    def set_entry_status(var, widg):
        print(var.get())
        if var.get():
            widg[-1]['state'] = 'normal'
        else:
            widg[-1]['state'] = 'disabled'
    
    def CustomWidget(frame, name, unit, ):
        var_e = []
        widget_e = []
    
        var_c = tk.IntVar(master=frame, value=0)
        widget_c = tk.Checkbutton(master=frame, text='', variable=var_c, command=lambda: set_entry_status(var_c, widget_e))
        widget_c.grid(row=0, column=0, columnspan=1, padx=5, pady=5, sticky="ns")
    
        label_l = name + " (" + unit + ")"  # nome + unità di misura in parentesi per GUI
        widget_l = tk.Label(frame, text=label_l, padx=1, pady=1)
        widget_l.grid(row=0, column=1, columnspan=1, padx=5, pady=5, sticky="wns")
    
        var_e.append(tk.StringVar(master=frame, value='A'))
        widget_e.append(tk.Entry(frame, textvariable=var_e[-1], width=10, state="normal"))  
        widget_e[-1].grid(row=0, column=2, columnspan=1, padx=5, pady=5, sticky="ns")
    
        var_e.append(tk.StringVar(master=frame, value='B'))
        widget_e.append(tk.Entry(frame, textvariable=var_e[-1], width=10, state="normal"))  
        widget_e[-1].grid(row=0, column=3, columnspan=1, padx=5, pady=5, sticky="ns")
    
        # set initial entry state
        if var_c.get():
            widget_e[-1]['state'] = 'normal'
        else:
            widget_e[-1]['state'] = 'disabled'
    
    root = tk.Tk()
    root.title('My Window')
    CustomWidget(root, 'name', 'unit')
    root.mainloop()