1

I have a very similar problem in Pyqt to that solved here and here, where one function is called with different parameters through a lambda.

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 2')
        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_()

My 2 questions are:

How can I make this work with default arguments? Is there a solution without using a lambda function? (The only reason I want this is because using lambda functions feels wrong and over-complicated and I feel there might be an easier solution.)

My (non-working) idea would look something like:

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 2')
        button1.clicked.connect(self.on_button()) # this should call on_button with n set to default
        #button1.clicked.connect(lambda: self.on_button()) #this works, but uses a lambda
        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=1): #using default argument
        print('Button {0} clicked'.format(n))

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    form = MyForm()
    form.show()
    app.exec_()
Dschoni
  • 3,714
  • 6
  • 45
  • 80

2 Answers2

1

If you want to not use a lambda, the syntax should be button1.clicked.connect(self.on_button).

But QPushButton::clicked has a boolean checked parameter (see the doc). So, the n parameter will never take the default value.

Dimitry Ernot
  • 6,256
  • 2
  • 25
  • 37
0

I usually use functools.partials for this case where a single slot handles multiple equivalent signals from different sources:

from functools import partial

# in __init__
button1.clicked.connect(self.on_button)
button1.clicked.connect(partial(self.on_button, n=2))

# and using a slot with kwarg n=1 as in your code

Under the hood this just creates an intermediate wrapper function whichs adds the kwarg, so this is very similar to a lambda and more a matter of taste than of true advantage.

Jeronimo
  • 2,268
  • 2
  • 13
  • 28