Tags Python , Qt

A 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.