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
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_())
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.
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 :)