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