猿问
下载APP

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

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

我正在尝试使用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)

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

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


幕布斯6054654
浏览 100回答 3
3回答

30秒到达战场

所述QPushButton.clicked信号发射指示按钮的状态的参数。当您连接到lambda插槽时,您指定的可选参数将idx被按钮的状态覆盖。相反,请将您的连接设为button.clicked.connect(lambda state, x=idx: self.button_pushed(x))这样就忽略了按钮状态,并将正确的值传递给您的方法。

123456qqq

谨防!只要您将信号连接到带有对self的引用的lambda插槽,您的小部件就不会被垃圾收集!那是因为lambda创建了一个闭包,其中包含对窗口小部件的另一个无法收集的引用。因此,self.someUIwidget.someSignal.connect(lambda p:self.someMethod(p))非常邪恶:)

米琪卡哇伊

我不确定你在这里使用lambda会出现什么问题。我认为这是因为idx(设置自动按钮时的循环索引)超出了范围,并且不再包含正确的值。但我认为你不需要这样做。看起来你使用lambda的唯一原因是你可以将一个参数传递给button_pushed(),以确定它是哪个按钮。sender()可以在button_pushed()槽中调用一个函数,该函数标识哪个按钮产生了信号。这是一个我认为你或多或少会拍摄的例子:from PyQt5.QtGui import *from PyQt5.QtCore import *from PyQt5.QtWidgets import *import sysclass MainWindow(QWidget):     def __init__(self):         super(QWidget, self).__init__()         main_layout = QVBoxLayout(self)         self.buttons = []         # Works:         self.button_1 = QPushButton('Button 1 manual', self)         main_layout.addWidget(self.button_1)         self.buttons.append(self.button_1)         self.button_1.clicked.connect(self.button_pushed)         self.button_2 = QPushButton('Button 2 manual', self)         main_layout.addWidget(self.button_2)         self.buttons.append(self.button_2)         self.button_2.clicked.connect(self.button_pushed)         # Doesn't work:         for idx in [3, 4]:             button = QPushButton('Button {} auto'.format(idx), self)             button.clicked.connect(self.button_pushed)             self.buttons.append(button)             main_layout.addWidget(button)     def button_pushed(self):         print('Pushed button {}'.format(self.buttons.index(self.sender())+1))app = QApplication(sys.argv)w = MainWindow()w.show()sys.exit(app.exec_())
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答