问题
Code example is from this answer.
When click a Button with a command function (and this command function itself will call another menu command function), like the code example, what would happen? When clicking Refresh menu
why has lambda command
show()
not been activated?
For clarity, I made some changes about the original code as below:
- comment out
Button().invoke
- add some
print()
information - and change/add some
counting variables
# Using lambda keyword and refresh function to create a dynamic menu.
# Set python script name as `tk_dynamic.py`
import tkinter as tk
choice_count = 0
refresh_count = 0
invoke_count = 1
def show(label, count):
""" Show your choice """
global label_choice, choice_count
choice_count += 1
new_label = 'Choice is: ' + label
menubar.entryconfigure(label_choice, label=new_label) # change menu text
label_choice = new_label # update menu label to find it next time
print("\nUpdate root menubar(id {})'s label as `{}`\n\
when adding command #{} to cascade menu(id {}) at refresh count {} in `show()`"\
.format(id(menubar), label_choice, count, id(menu), refresh_count))
choice.set(label)
print("Reset `variable choice` {} {} as {} in show() when adding command #{}\n"\
.format(choice_count, 'times' if choice_count > 1 else 'time', label, count))
def refresh():
""" Refresh menu contents """
global label_choice, label_cascade, refresh_count, choice_count
refresh_count += 1
if label_cascade[0] == 'one':
label_cascade = ['four', 'five', 'six', 'seven']
else:
label_cascade = ['one', 'two', 'three']
choice.set('')
choice_count = 0 # reset choice changing count
menu.delete(0, 'end') # delete previous contents of the menu
menubar.entryconfigure(label_choice, label=const_str) # change menu text
label_choice = const_str # update menu label to find it next time
print('\nUpdate root menubar(id {}) and set label as `{}` {} {} in `refresh()`'\
.format(id(menubar), label_choice, refresh_count, 'times' if refresh_count > 1 else 'time'))
command_count = 1
for l in label_cascade:
menu.add_command(label=l, command=lambda label=l, count=command_count: show(label, count))
print("Add command #{} to cascade menu(id {}) by calling show() at refresh count {}"\
.format(command_count, id(menu), refresh_count))
print("Choice change count is {} when adding command #{} at refresh count {}"\
.format(choice_count, command_count, refresh_count))
command_count += 1
root = tk.Tk()
# Set some variables
choice = tk.StringVar()
const_str = 'Choice'
label_choice = const_str
label_cascade = ['dummy']
# Create some widgets
menubar = tk.Menu(root)
root.configure(menu=menubar)
# menu = tk.Menu(menubar, tearoff=False)
menu = tk.Menu()
print('Before adding cascade menu(id {}) to root menubar(id {})'.format(id(menu), id(menubar)))
menubar.add_cascade(label=label_choice, menu=menu)
b = tk.Button(root, text='Refresh menu', command=refresh)
b.pack()
# b.invoke()
# print("Invoke {} {} button command"\
# .format(invoke_count, 'times' if invoke_count > 1 else 'time'))
# invoke_count += 1
print("Updating textvariable by changing variable choice {} {}"\
.format(choice_count, 'times' if choice_count > 1 else 'time'))
tk.Label(root, textvariable=choice).pack()
root.geometry("300x100")
root.mainloop()
print("This statement is after `mainloop()` and should print on closing window")
回答1:
When click a Button with a command function (and this command function itself will call another menu command function), like the code example, what would happen?
It's unclear what you're asking here. Tkinter has no control over this, the commands will run in the order that they are called.
When clicking Refresh menu why has lambda command show() not been activated?
lambda
doesn't call a function, it defines a new anonymous function. In this example, it creates a new function and assigns it to a menu item. The created function won't run until the user selects that item from the menu.
Let's look at this code:
menu.add_command(label=l, command=lambda label=l, count=command_count: show(label, count))
print("Add command #{} to cascade menu(id {}) by calling show() at refresh count {}"...
The statement being printed is incorrect. The code before it does not call show
. It creates a new anonymous function which will call show
when the menu item is selected.
来源:https://stackoverflow.com/questions/58807236/how-nested-tkinter-command-functions-work