Using lambda expression to connect slots in pyqt

前端 未结 3 1146
清酒与你
清酒与你 2020-11-22 12:06

I am trying to connect slots with lambda functions, but it\'s not working the way I expect. In the code below, I succeed in connecting the first two buttons correctly. For t

相关标签:
3条回答
  • 2020-11-22 12:51

    I'm not honestly sure what's going wrong with your use of lambda here either. I think it's because idx (your loop index when you set up the auto buttons) is going out of scope and doesn't contain the proper value anymore.

    But I don't think you need to do it this way. It looks like the only reason you're using lambda is so that you can pass an argument to button_pushed(), identifying which button it was. There's a function sender() that can be called in the button_pushed() slot which identifies which button originated the signal.

    Here's an example which I think does more or less what you were shooting for:

    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import *
    
    import sys
    
    class 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_())
    
    0 讨论(0)
  • 2020-11-22 12:56

    The QPushButton.clicked signal emits an argument that indicates the state of the button. When you connect to your lambda slot, the optional argument you assign idx to is being overwritten by the state of the button.

    Instead, make your connection as

    button.clicked.connect(lambda state, x=idx: self.button_pushed(x))
    

    This way the button state is ignored and the correct value is passed to your method.

    0 讨论(0)
  • 2020-11-22 13:09

    Beware! As soon as you connect your signal to a lambda slot with a reference to self, your widget will not be garbage-collected! That's because lambda creates a closure with yet another uncollectable reference to the widget.

    Thus, self.someUIwidget.someSignal.connect(lambda p: self.someMethod(p)) is very evil :)

    0 讨论(0)
提交回复
热议问题