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()