【发布时间】:2010-10-18 05:17:03
【问题描述】:
我有一个菜单按钮,单击它时应显示一个包含特定字符串序列的菜单。那个序列中到底是什么字符串,直到运行时我们才知道,所以弹出的菜单必须在那一刻生成。这是我所拥有的:
class para_frame(Frame):
def __init__(self, para=None, *args, **kwargs):
# ...
# menu button for adding tags that already exist in other para's
self.add_tag_mb = Menubutton(self, text='Add tags...')
# this menu needs to re-create itself every time it's clicked
self.add_tag_menu = Menu(self.add_tag_mb,
tearoff=0,
postcommand = self.build_add_tag_menu)
self.add_tag_mb['menu'] = self.add_tag_menu
# ...
def build_add_tag_menu(self):
self.add_tag_menu.delete(0, END) # clear whatever was in the menu before
all_tags = self.get_article().all_tags()
# we don't want the menu to include tags that already in this para
menu_tags = [tag for tag in all_tags if tag not in self.para.tags]
if menu_tags:
for tag in menu_tags:
def new_command():
self.add_tag(tag)
self.add_tag_menu.add_command(label = tag,
command = new_command)
else:
self.add_tag_menu.add_command(label = "<No tags>")
重要的部分是“if menu_tags:”下的内容——假设 menu_tags 是列表 ['stack', 'over', 'flow']。那么我想要做的实际上是这样的:
self.add_tag_menu.add_command(label = 'stack', command = add_tag_stack)
self.add_tag_menu.add_command(label = 'over', command = add_tag_over)
self.add_tag_menu.add_command(label = 'flow', command = add_tag_flow)
其中 add_tag_stack() 定义为:
def add_tag_stack():
self.add_tag('stack')
等等。
问题是,变量“tag”取值“stack”,然后取值“over”等等,直到调用 new_command,变量“tag”才会被评估只是“流动”。因此,无论用户点击什么,添加的标签始终是菜单上的最后一个标签。
我最初使用的是 lambda,我想也许像上面那样明确定义函数可能会更好。无论哪种方式都会出现问题。我尝试使用变量“tag”的副本(使用“current_tag = tag”或使用复制模块),但这并不能解决问题。我不知道为什么。
我的思绪开始徘徊在“eval”之类的东西上,但我希望有人能想出一个不涉及如此可怕的事情的聪明方法。
非常感谢!
(如果相关,Tkinter.__version__ 返回 '$Revision: 67083 $' 并且我在 Windows XP 上使用 Python 2.6.1。)
【问题讨论】:
标签: python lambda copy tkinter