Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass arguments to functions by the click of button in PyQt?

I want to pass the arguments to a function when I click the button. What should I add to this line button.connect(button, QtCore.SIGNAL('clicked()'), calluser(name)) so it will pass the value to the function:

def calluser(name):
    print name

def Qbutton():
    button = QtGui.QPushButton("button",widget)
    name = "user"
    button.setGeometry(100,100, 60, 35)
    button.connect(button, QtCore.SIGNAL('clicked()'), calluser(name))

One more thing, buttons will be generated using for loop; so name value will vary. So I want to attach each name with the button. I have done same thing in Pytk by using for loop and calling the argument base function when clicked.

like image 283
uahmed Avatar asked Jul 21 '11 23:07

uahmed


4 Answers

You can simply write

name = "user"
button.clicked.connect(lambda: calluser(name))
like image 87
ozcanyarimdunya Avatar answered Nov 10 '22 07:11

ozcanyarimdunya


I tried an efficient way of doing it and it worked out well for me. You can use the code:

from functools import partial

def calluser(name):
    print name

def Qbutton():
    button = QtGui.QPushButton("button",widget)
    name = "user"
    button.setGeometry(100,100, 60, 35)
    button.clicked.connect(partial(calluser,name))
like image 33
xeon Avatar answered Nov 10 '22 05:11

xeon


Usually GUIs are built using classes. By using bound methods as callbacks (see self.calluser below) you can "pass" information to the callback through self's attributes (e.g. self.name):

For example, using slightly modified code from this tutorial:

import sys
import PyQt4.QtCore as QtCore
import PyQt4.QtGui as QtGui

class QButton(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.button = QtGui.QPushButton('Button', self)
        self.name='me'
        self.button.clicked.connect(self.calluser)
    def calluser(self):
        print(self.name)

def demo_QButton():
    app = QtGui.QApplication(sys.argv)
    tb = QButton()
    tb.show()
    app.exec_()

if __name__=='__main__':
    demo_QButton()

Since the callback per se is always called with no additional arguments, when you need to pass distinct additional information to many callbacks, you need to make different callbacks for each button.

Since that can be laborious (if done manually), use a function factory instead. See below for an example. The function factory is a closure. It can be passed additional arguments, which the inner function can access when called:

class ButtonBlock(QtGui.QWidget):

    def __init__(self, *args):
        super(QtGui.QWidget, self).__init__()
        grid = QtGui.QGridLayout()
        names = ('One', 'Two', 'Three', 'Four', 'Five',
                 'Six', 'Seven', 'Eight', 'Nine', 'Ten')
        for i, name in enumerate(names):
            button = QtGui.QPushButton(name, self)
            button.clicked.connect(self.make_calluser(name))
            row, col = divmod(i, 5)
            grid.addWidget(button, row, col)
        self.setLayout(grid)

    def make_calluser(self, name):
        def calluser():
            print(name)
        return calluser

app = QtGui.QApplication(sys.argv)
tb = ButtonBlock()
tb.show()
app.exec_()
like image 33
unutbu Avatar answered Nov 10 '22 07:11

unutbu


Here is another way. --- PARTIAL -- I find this one most simple:

    widget = QWidget()
    widgetLayout = QVBoxLayout()

    for action in list:

        button = QPushButton("{action}".format(action=action['name']),self)
        button.clicked.connect(partial(self.action_selected,action=action['name']))
        widgetLayout.addWidget(button)

    widget.setLayout(widgetLayout)

def action_selected(self,action):
    print action

found on: http://tech-artists.org/forum/showthread.php?3118-PyQt-Maya-How-to-pass-arguments-to-a-function-when-connecting-it-to-PyQt-button

like image 5
Tomasz Edwin Avatar answered Nov 10 '22 05:11

Tomasz Edwin