您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

python – 在Tkinter中动态创建菜单. (lambda表达式?)

5b51 2022/1/14 8:23:09 python 字数 4495 阅读 624 来源 www.jb51.cc/python

我有一个menubutton,点击它时会显示一个包含特定字符串序列的菜单.正是这个序列中的字符串,我们直到运行时才知道,所以必须在那一刻生成弹出的菜单.这就是我所拥有的: class para_frame(Frame): def __init__(self, para=None, *args, **kwargs): # ... # menu button

概述

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

items = ["stack","over","flow"]
map = { }

for item in items:
    def new_command():
        print(item)

    map[item] = new_command

map["stack"]()
map["over"]()
map["flow"]()

现在,当我们执行此操作时,正如您所说,我们得到:

flow
flow
flow

这里的问题是Python的范围概念.特别是,for语句不会引入新的范围,也不会引入新的项目绑定;所以每次循环都会更新相同的项变量,并且所有new_command()函数都引用同一个项.

您需要做的是为每个项目引入一个新的范围,并使用新的绑定.最简单的方法是将其包装在一个新的函数定义中:

for item in items:
    def item_command(name):
        def new_command():
            print(name)
        return new_command

    map[item] = item_command(item)

现在,如果您将其替换为前面的程序,您将获得所需的结果:

stack
over
flow

总结

以上是编程之家为你收集整理的python – 在Tkinter中动态创建菜单. (lambda表达式?)全部内容,希望文章能够帮你解决python – 在Tkinter中动态创建菜单. (lambda表达式?)所遇到的程序开发问题。


如果您也喜欢它,动动您的小指点个赞吧

除非注明,文章均由 laddyq.com 整理发布,欢迎转载。

转载请注明:
链接:http://laddyq.com
来源:laddyq.com
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


联系我
置顶