Home > Blockchain >  How to handle variables of multiple check buttons inside a menu in Tkinter?
How to handle variables of multiple check buttons inside a menu in Tkinter?

Time:04-12

I wanted to make a multi-selection dropdown list in Tkinter so browsing online I came to the solution of using add_checkbuttons into a menu. The solution it's working, at least graphically, but now I want the GUI to actually do something when a check is marked. I tried with a simple function that print the value as a command for each check button but it's only being called once.

Here's my code so far:

root = tk.Tk()

groceries = ['Apple', 'Banana', 'Carrot']

def print_groceries(bucket,item):
    print(bucket[item].get())

menubar = tk.Menu(root)
viewMenu = tk.Menu(menubar, tearoff = 0)
bucket={}
for item in groceries:
    bucket[item] = tk.BooleanVar(False)
    viewMenu.add_checkbutton(label = item, variable = bucket[item], command=print_groceries(bucket,item))
menubar.add_cascade(menu = viewMenu, label = "Buy")
root.config(menu = menubar)

root.mainloop()

CodePudding user response:

You have assigned the return value of print_groceries to the command parameter. Therefore, when your code is executed, print_groceries is executed thrice at the time of defining the checkbuttons. As all the checkbuttons are unchecked initially, you see that False is printed thrice.


Solution:

The command parameter takes a function, not the value returned by a function (unless the return value is itself a function).

To create a simple function, you can use lambda as shown below:

lambda <parameter-1>,<parameter-2>,... : <task-to-perform>

Also, you must use lambda bucket=bucket, item=item: print_groceries(bucket,item) and not lambda : print_groceries(bucket,item). You can find the reason for the same in this answer.


Working Code:

import tkinter as tk

root = tk.Tk()

groceries = ['Apple', 'Banana', 'Carrot']

def print_groceries(bucket,item):
    print(bucket[item].get())

menubar = tk.Menu(root)
viewMenu = tk.Menu(menubar, tearoff = 0)
bucket={}
for item in groceries:
    bucket[item] = tk.BooleanVar(False)
    func = lambda bucket=bucket, item=item: print_groceries(bucket,item)
    viewMenu.add_checkbutton(label = item, variable = bucket[item], command = func)
menubar.add_cascade(menu = viewMenu, label = "Buy")
root.config(menu = menubar)

root.mainloop()
  • Related