Passing extra arguments to PyQt slots
April 25th, 2011 at 1:38 pmA frequent question coming up when programming with PyQt is how to pass extra arguments to slots. After all, the signal-slot connection mechanism only specifies how to connect a signal to a slot – the signal’s arguments are passed to the slot, but no additional (user-defined) arguments may be directly passed.
But passing extra arguments can be quite useful. You can have a single slot handling signals from multiple widgets, and sometimes you need to pass extra information.
One way to do this is using lambda. Here’s a complete code sample:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyForm(QMainWindow):
def __init__(self, parent=None):
super(MyForm, self).__init__(parent)
button1 = QPushButton('Button 1')
button2 = QPushButton('Button 1')
button1.clicked.connect(lambda: self.on_button(1))
button2.clicked.connect(lambda: self.on_button(2))
layout = QHBoxLayout()
layout.addWidget(button1)
layout.addWidget(button2)
main_frame = QWidget()
main_frame.setLayout(layout)
self.setCentralWidget(main_frame)
def on_button(self, n):
print('Button {0} clicked'.format(n))
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
form = MyForm()
form.show()
app.exec_()
Note how the on_button slot is used to handle signals from both buttons. Here we use lambda to pass the button number to the slot, but anything can be passed – even the button widget itself (suppose the slot wants to deactivate the button that sent the signal).
There’s an alternative to lambda – using functools.partial. We can replace the connection lines with:
button1.clicked.connect(partial(self.on_button, 1))
button2.clicked.connect(partial(self.on_button, 2))
Which method is better? It’s really a matter of style. Personally, I prefer the lambda because it’s more explicit and flexible.
Related posts:

April 27th, 2011 at 13:02
A potential problem for beginners with lambda is that it will not evaluate/look up the argument values before it is effectively called, breaking situations like using a loop variable inside it.
AFAIR in PySide (an LGPL PyQt alternative) we had an user with exactly this problem, connecting a handful of buttons using lambdas in a for loop and clicking any button triggered only the last registered action.
April 27th, 2011 at 13:07
Lauro,
Interesting – thanks!
May 1st, 2011 at 20:17
But, does this work for SIGNALs that actually pass a value to the slot ???
May 2nd, 2011 at 05:13
anonymous,
Sure – for those, the
lambdahas to take parameters (the amount the signal passes), and pass them to the slot along with the user’s extra parameters.June 15th, 2011 at 23:43
Correct me if I’m wrong but I have noticed that lambdas are not disconnected from signals even when qt objects contained in the lambda are deleted, which could give a lot of errors.
June 16th, 2011 at 07:41
Christopher,
Can you find a concrete example that demonstrates this problem?
November 27th, 2011 at 12:56
This is a very well written blog, keep up the good work!
I’m working on an crossplatform embedded controller, communication through PySerial and a PyQt GUI. You just saved me a whole day of work
.
December 16th, 2011 at 19:15
Hi,
Thanks for this useful tip. But I am having the exact situation Lauro described. I have several images in a scroll area generated in a loop and I want to connect each image to a function with a parameter depending on the loop. How can I do that ?
December 17th, 2011 at 01:14
Johanna,
What you can do is have another function generate the
lambda, i.e. something like:And in the connection, call
make_callback(i). Then a differentlambdais created for each iteration.December 19th, 2011 at 10:36
Thanks for your response, but I didn’t get it to work yet.
What I did is :
in my loop thatcreates the images I do :
Then I define
What am I doing wrong ?
December 20th, 2011 at 08:51
Johanna,
I don’t think you need the
lambda:here.connectexpects a function as its third argument, andself.make_callbackalready returns a function.December 20th, 2011 at 10:10
Great! Thank you very much for your help, you saved a lot of hair pulling over here
April 19th, 2012 at 15:34
Hi , Thank you for this helpful blog
I struggled how to pass multiple arguments in Qobject.connect , but finally
it’s very helpful
cheers
April 27th, 2012 at 13:03
Hi, thanks for the post.
I experienced some problems when I wanted to use the lambda solution for appending a value to a signal which is sending its own values. So, at the end I had to use the partial function.
Do you know the way of doing so with lambda?
Regards,
Germán
April 27th, 2012 at 13:07
Germán,
Python
lambdaforms are syntactically restricted to a single expression. Anything that doesn’t count as a single expression can’t go into alambda.July 13th, 2012 at 16:24
maybe wrong way, but that work for me and has ability to pass any amount of args
July 30th, 2012 at 16:35
Thanks Saved a lot of time .. . .
August 3rd, 2012 at 04:23
Thanks a lot for this post. I was fighting with the problem of passing extra arguments for a while until I found it. Many many thanks!
May 11th, 2013 at 22:28
Unfortunately, neither of these solutions seem to work when the destination object is in a different QThread. The object ends up executing in the main QThread when its given a lambda function, whereas it correctly executes in the worker thread when its given no arguments.