【问题标题】:Create PyQt menu from a list of strings从字符串列表创建 PyQt 菜单
【发布时间】:2010-11-09 04:52:40
【问题描述】:

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

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”而不是对应的。我很感谢任何关于我如何才能做到这一点的想法。谢谢。

【问题讨论】:

    标签: python qt pyqt signals-slots


    【解决方案1】:

    您遇到了在 Python 中经常被称为“范围问题”的问题(可能并不完全是迂腐正确的;-)——当您愿意时,绑定是迟到的(调用时的词法查找)早期(在默认时间)。那么您现在拥有的位置:

        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 这里的一个)在def-time 被计算一次。添加一层函数嵌套(例如双 lambda)也可以,但在这里有点过头了!-)

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

    【讨论】:

    • 优秀的答案!它也适用于新的连接语法:entry.triggered.connect(lambda item=item: self.doStuff(item))
    • 这是一个很好的答案。为了更容易看到发生了什么(大约 12 年后),lambda 位可以这样重写:lambda foo=item: self.doStuff(foo),而不是重新使用名称 item,它会影响外部范围。
    【解决方案2】:

    这应该可行,但我很确定有更好的方法,我现在想不起来了。

    def do_stuff_caller(self, item):
        return lambda: self.doStuff(item)
    
    ...
    self.connect(entry, QtCore.SIGNAL('triggered()'), self.do_stuff_caller(item))
    

    编辑: 较短的版本,这仍然不是我在想的......或者它可能是另一种语言? :)

    (lambda x: lambda self.do_stuff(x))(item)

    【讨论】:

      猜你喜欢
      • 2011-04-20
      • 2016-02-13
      • 2016-12-02
      • 1970-01-01
      • 2014-02-10
      • 1970-01-01
      • 2020-04-21
      • 2013-08-11
      • 1970-01-01
      相关资源
      最近更新 更多