使用lambda表达式连接pyqt中的插槽

zeu*_*300 6 python lambda pyqt

我正在尝试使用lambda函数连接插槽,但它没有按照我期望的方式工作.在下面的代码中,我成功正确连接前两个按钮.对于我在循环中连接的后两个,这是错误的.在我之前有人有同样的问题(Qt - 使用lambda连接带有参数的插槽),但这个解决方案对我不起作用.我一直盯着我的屏幕半小时,但我无法弄清楚我的代码是如何不同的.

class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(QtGui.QWidget, self).__init__()

        main_layout = QtGui.QVBoxLayout(self)

        # Works:
        self.button_1 = QtGui.QPushButton('Button 1 manual', self)
        self.button_2 = QtGui.QPushButton('Button 2 manual', self)
        main_layout.addWidget(self.button_1)
        main_layout.addWidget(self.button_2)

        self.button_1.clicked.connect(lambda x:self.button_pushed(1))
        self.button_2.clicked.connect(lambda x:self.button_pushed(2))

        # Doesn't work:
        self.buttons = []
        for idx in [3, 4]:
            button = QtGui.QPushButton('Button {} auto'.format(idx), self)
            button.clicked.connect(lambda x=idx: self.button_pushed(x))
            self.buttons.append(button)
            main_layout.addWidget(button)


    def button_pushed(self, num):
        print 'Pushed button {}'.format(num)
Run Code Online (Sandbox Code Playgroud)

按下前两个按钮会产生'Pushing button 1'和'Pushing button 2',另外两个按钮都会产生'Pushed button False',虽然我预计会有3和4.

我还没有完全理解lambda机制.究竟有什么联系?指向由lambda生成的函数的指针(使用参数替换)或者是在信号触发时评估的lambda函数?

thr*_*les 31

所述QPushButton.clicked信号发射指示按钮的状态的参数.当您连接到lambda插槽时,您指定的可选参数将idx被按钮的状态覆盖.

相反,请将您的连接设为

button.clicked.connect(lambda state, x=idx: self.button_pushed(x))
Run Code Online (Sandbox Code Playgroud)

这样就忽略了按钮状态,并将正确的值传递给您的方法.

  • @ioaniatr 当您连接到“clicked”信号时,该信号具有 [此处](http://doc.qt.io/qt-5/qabstractbutton.html#clicked) 描述的签名。如您所见,当发出信号时,会提供一个参数,其中包含按钮的状态(是否选中按钮)。我的代码中的变量可以随意调用,但它必须在那里,以便 Qt 不会用选中的状态覆盖下一个参数 (`x=idx`)。 (2认同)

Gri*_*eev 9

谨防!只要您将信号连接到带有对self的引用的lambda插槽,您的小部件就不会被垃圾收集!那是因为lambda创建了一个闭包,其中包含对窗口小部件的另一个无法收集的引用.

因此,self.someUIwidget.someSignal.connect(lambda p:self.someMethod(p))非常邪恶:)

  • 那么有什么替代方案呢? (3认同)
  • @Esostack:取决于你想要实现的目标。如果您只想检测插槽中哪个对象发出了信号,您可以使用“QObject.sender()”方法。此外,您可以将信息存储在小部件属性中并在槽函数中访问它们,请参阅此示例:/sf/ask/3461278271/ (2认同)