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.
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_()
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))
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
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!
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