Comment passer des arguments aux fonctions de callback dans PyQt

j'ai environ 10 QAction (ce nombre variera en exécution) dans une barre d'outils, qui tous feront la même chose, mais en utilisant des paramètres différents. Je pense à ajouter un paramètre en tant qu'attribut à l'objet QAction, et ensuite, le signal déclenché par QAction enverra aussi l'objet lui-même à la fonction de rappel, de sorte que je pourrais obtenir les paramètres requis pour la fonction. J'ai en fait 2 questions à ce sujet:

  • est-ce possible?
  • est il y a une meilleure manière de faire ceci?
8
demandé sur yasar 2012-01-11 22:03:21

5 réponses

vous pouvez envoyer l'objet d'action lui-même en utilisant un signal mapper . Toutefois, il peut être préférable d'envoyer simplement un identificateur et de faire tout le travail au sein du gestionnaire de signal.

voici un script de démo simple:

from PyQt4 import QtGui, QtCore

class Window(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.mapper = QtCore.QSignalMapper(self)
        self.toolbar = self.addToolBar('Foo')
        self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
        for text in 'One Two Three'.split():
            action = QtGui.QAction(text, self)
            self.mapper.setMapping(action, text)
            action.triggered.connect(self.mapper.map)
            self.toolbar.addAction(action)
        self.mapper.mapped['QString'].connect(self.handleButton)
        self.edit = QtGui.QLineEdit(self)
        self.setCentralWidget(self.edit)

    def handleButton(self, identifier):
        if identifier == 'One':
            text = 'Do This'
        elif identifier == 'Two':
            text = 'Do That'
        elif identifier == 'Three':
            text = 'Do Other'
        self.edit.setText(text)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.resize(300, 60)
    window.show()
    sys.exit(app.exec_())
4
répondu ekhumoro 2012-01-11 18:47:56

Comment passer des arguments aux fonctions de rappel dans PyQt

vous pouvez utiliser functools.partial de la bibliothèque standart Python. Exemple avec QAction :

some_action.triggered.connect(functools.partial(some_callback, param1, param2))
39
répondu reclosedev 2012-01-11 18:35:15

vous pouvez utiliser une fonction lambda associée au slot du contrôle GUI pour passer des arguments supplémentaires à la méthode que vous voulez exécuter.

# Create the build button with its caption
self.build_button = QPushButton('&Build Greeting', self)
# Connect the button's clicked signal to AddControl
self.build_button.clicked.connect(lambda: self.AddControl('fooData'))
def AddControl(self, name):
    print name

Source: snip2code - à l'Aide d'une Fonction Lambda De Passer en Argument Supplémentaire en PyQt4

9
répondu Dominique Terrs 2013-11-03 10:43:30

la meilleure façon de passer les arguments est de ne pas les passer du tout. Vous pouvez utiliser la nature dynamique de python, et définir toutes les données dont vous avez besoin comme vos propres propriétés sur les widgets eux-mêmes, obtenir le widget cible dans le handler en utilisant self.sender() , et puis obtenir toutes les propriétés dont vous avez besoin directement à partir du widget.

dans cet exemple cinq boutons sont créés et l'État requis est défini sur le widget de bouton comme my_own_data propriété:

import sys
from PyQt4 import QtGui, QtCore

class Main(QtGui.QMainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.centralwidget = QtGui.QWidget()
        self.vboxlayout = QtGui.QVBoxLayout()

        for idx in range(5):
            button = QtGui.QPushButton('button ' + str(idx), None)
            button.my_own_data = str(idx)  # <<< set your own property
            button.clicked.connect(self.click_handler)  # <<< no args needed
            self.vboxlayout.addWidget(button)

        self.centralwidget.setLayout(self.vboxlayout)
        self.setCentralWidget(self.centralwidget)
        self.show()

    def click_handler(self, data=None):
        if not data:
            target = self.sender()  # <<< get the event target, i.e. the button widget
            data = target.my_own_data  # <<< get your own property
        QtGui.QMessageBox.information(self, 
                                      "you clicked me!", 
                                      "my index is {0}".format(data))

app = QtGui.QApplication(sys.argv)
main = Main()
main.show()

sys.exit(app.exec_())
3
répondu ccpizza 2015-12-30 00:04:59

il y a encore un bug dans la façon dont PyQt utilise QSignalMapper. J'ai découvert un travail-ici:

http://www.riverbankcomputing.com/pipermail/pyqt/2010-March/026113.html

pour corriger la question répondue faire la modification suivante:

        action.triggered[()].connect(self.mapper.map)

cela était nécessaire pour la version suivante de Python:

Python 2.6.6 (r266:84292, Feb 21 2013, 19:26:11)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
1
répondu John Wasinger 2013-09-05 17:22:34