代码示例来自this answer。
[单击带有命令功能的按钮(此命令功能本身将调用另一个菜单命令功能),如代码示例所示,会发生什么?单击Refresh menu
时,为什么未激活lambda command
show()
?
为清楚起见,我对原始代码进行了如下更改:
Button().invoke
print()
信息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")
这不应该是最佳的答案,而是问题所有者的实验记录。我的初步结论是在step 1 and 2
处,并采取以下步骤进行分析确认。
python 3.7.5
和TkVersion 8.6
运行的结果:python tk_dynamic.py
运行以进行初始化。标准输出:Before adding cascade menu(id 4382568272) to root menubar(id 4382495440)
Updating textvariable by changing variable choice 0 time
目前,我们尚未调用Button command
,因此cascade menu
中没有任何内容。并且root menubar label
被初始化为Choice
。单击它,没有下拉菜单提示。
Refresh menu
,现在通过下拉菜单root menubar label
将Choice
重置为['one', 'two', 'three']
(刷新初始label_cascade = ['dummy']
时,我们转到2nd
的if-else
分支]语句。)注意,目前我们尚未在循环中调用lambada
command
,并且choice change count
不会更改。
Update root menubar(id 4382495440) and set label as `Choice` 1 time in `refresh()`
Add command #1 to cascade menu(id 4382568272) by calling show() at refresh count 1
Choice change count is 0 when adding command #1 at refresh count 1
Add command #2 to cascade menu(id 4382568272) by calling show() at refresh count 1
Choice change count is 0 when adding command #2 at refresh count 1
Add command #3 to cascade menu(id 4382568272) by calling show() at refresh count 1
Choice change count is 0 when adding command #3 at refresh count 1
Refresh menu
。请注意,choice change count
仍为0
。但是由于在此刷新时间['four', 'five', 'six', 'seven']
处的label_cascade[0] = 'one'
,下拉菜单更改为2
。 Update root menubar(id 4382495440) and set label as `Choice` 2 times in `refresh()`
Add command #1 to cascade menu(id 4382568272) by calling show() at refresh count 2
Choice change count is 0 when adding command #1 at refresh count 2
Add command #2 to cascade menu(id 4382568272) by calling show() at refresh count 2
Choice change count is 0 when adding command #2 at refresh count 2
Add command #3 to cascade menu(id 4382568272) by calling show() at refresh count 2
Choice change count is 0 when adding command #3 at refresh count 2
Add command #4 to cascade menu(id 4382568272) by calling show() at refresh count 2
Choice change count is 0 when adding command #4 at refresh count 2
four
,根菜单栏标签更改为Choice is: four
,新的可见标签four
将在按钮Refresh menu
下方提示。每次我们单击dropdown command
时,choice count
将为+1
。 Update root menubar(id 4382495440)'s label as `Choice is: four`
when adding command #1 to cascade menu(id 4382568272) at refresh count 2 in `show()`
Reset `variable choice` 1 time as four in show() when adding command #1
seven
,根菜单栏标签更改为Choice is: seven
,新的可见标签seven
将在按钮Refresh menu
下方提示。请注意,command #4
表示seven
是label_cascade
中的4th
refresh() loop
中要处理的最后一个项目。如果我们多次单击seven
,则command #4
保持不变,并且choice count
继续增加。Update root menubar(id 4382495440)'s label as `Choice is: seven` when adding command #4 to cascade menu(id 4382568272) at refresh count 2 in `show()` Reset `variable choice` 2 times as seven in show() when adding command #4
Update root menubar(id 4382495440)'s label as `Choice is: seven` when adding command #4 to cascade menu(id 4382568272) at refresh count 2 in `show()` Reset `variable choice` 3 times as seven in show() when adding command #4
Refresh menu
,将choice count
重置为0
,将根菜单栏标签重置为Choice
,其下拉菜单切换为['one', 'two', 'three']
。注意refresh count
将继续增加,并且当前循环的迭代时间为3
Update root menubar(id 4382495440) and set label as `Choice` 3 times in `refresh()`
Add command #1 to cascade menu(id 4382568272) by calling show() at refresh count 3
Choice change count is 0 when adding command #1 at refresh count 3
Add command #2 to cascade menu(id 4382568272) by calling show() at refresh count 3
Choice change count is 0 when adding command #2 at refresh count 3
Add command #3 to cascade menu(id 4382568272) by calling show() at refresh count 3
Choice change count is 0 when adding command #3 at refresh count 3
print()
This statement is after `mainloop()` and should print on closing window