rishis3d
rishis3d

Reputation: 199

Using Single Python Def for Mulitple QpushButton base on Clicked

I am doing a GUI with lots of buttons. With multiple selection option at a time.

I want to know how to connect a single Python Def for all buttons with Clicked() Button name as a arg?

Upvotes: 1

Views: 2913

Answers (2)

jsbueno
jsbueno

Reputation: 110696

An easy way is to create small functions - which can be lambdas, or objects as returned by functools.partial - that are connected to the actual Qt event. These mini-functions in turn, call your main callback, passing as many parameters as you like:

# coding: utf-8

from PyQt4 import QtCore, QtGui

app = QtGui.QApplication([])
window = QtGui.QWidget()
grid = QtGui.QGridLayout()

def callback(button):
   print button

for x in range(10):
   b = QtGui.QPushButton()
   b.setText(unicode(x))
   grid.addWidget(b, 0, x)
   window.connect(b, QtCore.SIGNAL("clicked()"), (lambda y:lambda: callback(y) )(x))
   b.show()

window.setLayout(grid)
window.show()
app.exec_()

Notice you have to use an "enclosing lambda" for the actuall lambda which is the callback, in order to "freeze" the value of x for each loop iteration.If the expression to the connect call where just lambda: callback(x), x would be evaluated at keypress time, and would therefore be 9, in this case, for all buttons.

The main callback function, however, is just one, just as you asked for.

Upvotes: 0

Avaris
Avaris

Reputation: 36735

Use a QButtonGroup and its buttonClicked signal. You'll get the id or the QPushButton itself.

Edit

A simple example:

import sys
from PyQt4 import QtGui

class Widget(QtGui.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        # Arrange buttons horizontally
        buttonLayout = QtGui.QHBoxLayout()

        # QButtonGroup to keep track of buttons
        self.buttonGroup = QtGui.QButtonGroup()

        # Connect the 'buttonClicked' signal 'self.setLabel'
        # There are two overloads for 'buttonClicked' signal: QAbstractButton (button itself) or int (id)
        # Specific overload for the signal is selected via [QtGui.QAbstractButton]
        # Clicking any button in the QButtonGroup will send this signal with the button
        self.buttonGroup.buttonClicked[QtGui.QAbstractButton].connect(self.setLabel)

        for i in range(5): # Let's create 5 button
            button = QtGui.QPushButton('%d' % i)     # make a button
            buttonLayout.addWidget(button)           # add to layout
            self.buttonGroup.addButton(button)       # add to QButtonGroup
            #self.buttonGroup.addButton(button, i)    # You can give an 'id' if you like

        self.label = QtGui.QLabel()  # just to write some output

        # lay everything out
        layout = QtGui.QVBoxLayout()
        layout.addLayout(buttonLayout)
        layout.addWidget(self.label)
        self.setLayout(layout)

    def setLabel(self, button):
        # clicking any button will call this slot 
        # 'button' argument will be the button itself
        # so... let's show its text in the label:
        self.label.setText('You clicked button with text "%s"' % button.text())


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    widget = Widget()
    widget.show()
    app.exec_()

Upvotes: 6

Related Questions