从字符串列表创建 PyQt 菜单 [英] Create PyQt menu from a list of strings

查看:25
本文介绍了从字符串列表创建 PyQt 菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个字符串列表,想为每个字符串创建一个菜单项.当用户单击其中一个条目时,将始终以字符串作为参数调用相同的函数.经过一些尝试和研究,我想出了这样的事情:

I have a list of strings and want to create a menu entry for each of those strings. When the user clicks on one of the entries, always the same function shall be called with the string as an argument. After some trying and research I came up with something like this:

import sys
from PyQt4 import QtGui, QtCore

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.menubar = self.menuBar()
        menuitems = ["Item 1","Item 2","Item 3"]
        menu = self.menubar.addMenu('&Stuff')
        for item in menuitems:
            entry = menu.addAction(item)
            self.connect(entry,QtCore.SIGNAL('triggered()'), lambda: self.doStuff(item))
            menu.addAction(entry)
        print "init done"

    def doStuff(self, item):
        print item

app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())

现在的问题是每个菜单项都会打印相同的输出:Item 3"而不是相应的输出.我很感谢您提供有关如何正确处理此问题的任何想法.谢谢.

Now the problem is that each of the menu items will print the same output: "Item 3" instead of the corresponding one. I'm thankful for any ideas about how I can get this right. Thanks.

推荐答案

您遇到了在 Python 中经常被称为(可能不完全是迂腐的——正确的;-)的问题——绑定迟到了(在调用时进行词法查找),而您希望尽早(在定义时).所以你现在有:

You're meeting what's been often referred to (maybe not entirely pedantically-correctly;-) as the "scoping problem" in Python -- the binding is late (lexical lookup at call-time) while you'd like it early (at def-time). So where you now have:

    for item in menuitems:
        entry = menu.addAction(item)
        self.connect(entry,QtCore.SIGNAL('triggered()'), lambda: self.doStuff(item))

尝试:

    for item in menuitems:
        entry = menu.addAction(item)
        self.connect(entry,QtCore.SIGNAL('triggered()'), lambda item=item: self.doStuff(item))

这预期"了绑定,因为默认值(如这里的 item 之一)在定义时一次性计算一次.添加一层函数嵌套(例如双 lambda)也可以,但这里有点矫枉过正!-)

This "anticipates" the binding, since default values (as the item one here) get computed once an for all at def-time. Adding one level of function nesting (e.g. a double lambda) works too, but it's a bit of an overkill here!-)

您也可以使用 functools.partial(self.doStuff, item)(当然在顶部带有 import functools)这是另一个很好的解决方案,但我我想我会选择最简单(也是最常见的)参数的假默认值"习语.

You could alternatively use functools.partial(self.doStuff, item) (with an import functools at the top of course) which is another fine solution, but I think I'd go for the simplest (and most common) "fake default-value for argument" idiom.

这篇关于从字符串列表创建 PyQt 菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆