从字符串列表创建 PyQt 菜单 [英] Create PyQt menu from a list of strings
问题描述
我有一个字符串列表,想为每个字符串创建一个菜单项.当用户单击其中一个条目时,将始终以字符串作为参数调用相同的函数.经过一些尝试和研究,我想出了这样的事情:
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屋!