我有一个menubutton,点击它时会显示一个包含特定字符串序列的菜单.正是这个序列中的字符串,我们直到运行时才知道,所以必须在那一刻生成弹出的菜单.这就是我所拥有的:
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 = "")
重要的部分是“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.)