web-dev-qa-db-fra.com

Comment passer des arguments à des fonctions par le clic de bouton dans PyQt?

Je souhaite transmettre les arguments à une fonction lorsque je clique sur le bouton. Que dois-je ajouter à cette ligne button.connect(button, QtCore.SIGNAL('clicked()'), calluser(name)) pour qu'il transmette la valeur à la fonction:

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))

Une dernière chose, les boutons seront générés en utilisant la boucle for; alors name valeur variera. Donc, je veux attacher chaque nom avec le bouton. J'ai fait la même chose dans Pytk en utilisant la boucle for et en appelant la fonction de base d'argument lorsque l'utilisateur clique dessus.

15
uahmed

Généralement, les interfaces graphiques sont construites à l'aide de classes. En utilisant des méthodes liées en tant que rappels (voir self.calluser ci-dessous), vous pouvez "transmettre" des informations au rappel via les attributs de self (par exemple, self.name):

Par exemple, en utilisant un code légèrement modifié à partir de ce tutoriel

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()

Étant donné que le rappel en soi est toujours appelé sans arguments supplémentaires, lorsque vous devez transmettre des informations supplémentaires distinctes à plusieurs rappels, vous devez effectuer des rappels différents pour chaque bouton. 

Comme cela peut être laborieux (si cela est fait manuellement), utilisez plutôt une fabrique de fonctions. Voir ci-dessous pour un exemple. La fabrique de fonctions est une fermeture. On peut lui transmettre des arguments supplémentaires, auxquels la fonction interne peut accéder lorsqu'elle est appelée:

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_()
25
unutbu

J'ai essayé un moyen efficace de le faire et cela a bien fonctionné pour moi. Vous pouvez utiliser le 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))
6
xeon

Voici un autre moyen. --- PARTIAL - Je trouve celui-ci le plus 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

trouvé sur: http://tech-artists.org/forum/showthread.php?3118-PyQt-Maya-How-to-pass-arguments-to-a-function-when-connecting- Bouton PyQt

3
Tomasz Edwin

En Python, les instances de classe sont appelables. Vous pouvez simplement utiliser une instance d'une classe en tant que fonction. Cette classe peut contenir ce que vous voulez. (Dans certains langages ou frameworks, un objet appelable est appelé un foncteur ou un objet fonction .)

class CallUser:
    def __init__(self, name):
        self.name = name
    def __call__(self):
        print(self.name)

def Qbutton():
    button = QtGui.QPushButton("button",widget)
    name = "user"
    button.setGeometry(100,100, 60, 35)
    button.clicked.connect(CallUser(name))
    # Object of type CallUser will work as a function!
0
eje211

Le code ci-dessous illustre une méthode d'association de données avec des boutons générés. Par exemple, vous pouvez modifier l'instruction self.keydata[b] = key pour stocker un nuage de données dans self.keydata[b] à utiliser lors du traitement ultérieur d'un événement de bouton.

Notez que, dans le code suivant, assets est un dictionnaire précédemment défini contenant des titres pour les boutons. Dans la routine processButton(self), self.sender() est égal à une entrée de la variable de classe buttons[].

class Tab5(QtGui.QWidget):
    buttons, keydata = {}, {}
    def __init__(self, fileInfo, parent=None):
        super(Tab5, self).__init__(parent)
        layout = QtGui.QVBoxLayout()

        for key in sorted(assets):
            b = self.buttons[key] = QtGui.QPushButton(assets[key], self)
            b.clicked.connect(self.processButton)
            layout.addWidget(b)
            print 'b[key]=',b, ' b-text=',assets[key]
            self.keydata[b] = key

        layout.addStretch(1)
        self.setLayout(layout)

    def processButton(self):
         print 'sender=',self.sender(), ' s-text=',self.sender().text(), ' data[.]=', self.keydata[self.sender()] 
         pass

Le résultat obtenu était le suivant: les quatre premières lignes étaient imprimées au cours de la boucle for et les quatre dernières étaient imprimées lorsque les quatre boutons étaient enfoncés dans l’ordre.

b[key]= <PySide.QtGui.QPushButton object at 0x7f382f2ca830>  b-text= K1
b[key]= <PySide.QtGui.QPushButton object at 0x7f382f2ca908>  b-text= K2
b[key]= <PySide.QtGui.QPushButton object at 0x7f382f2ca950>  b-text= K3
b[key]= <PySide.QtGui.QPushButton object at 0x7f382f2ca998>  b-text= K4
sender= <PySide.QtGui.QPushButton object at 0x7f382f2ca830>  s-text= K1  data[.]= L1
sender= <PySide.QtGui.QPushButton object at 0x7f382f2ca908>  s-text= K2  data[.]= L2
sender= <PySide.QtGui.QPushButton object at 0x7f382f2ca950>  s-text= K3  data[.]= L3
sender= <PySide.QtGui.QPushButton object at 0x7f382f2ca998>  s-text= K4  data[.]= L4
0