¿Cómo pasar argumentos a las funciones con el clic del botón en PyQt?

Quiero pasar los argumentos a una función cuando hago clic en el botón. ¿Qué debo agregar a esta línea button.connect(button, QtCore.SIGNAL('clicked()'), calluser(name)) para que pase el valor a la función:

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

Una cosa más, los botones se generarán usando for loop; así name valor del name variará. Así que quiero adjuntar cada nombre con el botón. He hecho lo mismo en Pytk utilizando bucle y llamando a la función de base de argumentos cuando se hace clic.

Usualmente las GUIs son construidas usando clases. Al usar los métodos enlazados como devoluciones de llamada (consulte self.calluser abajo) puede “pasar” información a la callback a través de los atributos de self (por ejemplo, self.name ):

Por ejemplo, usando un código ligeramente modificado de este 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() 

Dado que la callback en sí misma siempre se realiza sin argumentos adicionales, cuando necesita pasar información distinta a muchas devoluciones de llamada, debe realizar diferentes devoluciones de llamada para cada botón.

Como eso puede ser laborioso (si se hace manualmente), use una función de fábrica en su lugar. Vea a continuación un ejemplo. La fábrica de funciones es un cierre. Se pueden pasar argumentos adicionales, a los que la función interna puede acceder cuando se llama:

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

Probé una forma eficiente de hacerlo y funcionó bien para mí. Puedes usar el código:

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

Aquí hay otra manera. — PARCIAL – Encuentro este mas 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 

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

El código que se muestra a continuación ilustra un método para asociar datos con botones generados. Por ejemplo, puede cambiar la instrucción self.keydata[b] = key para almacenar una tupla de datos en self.keydata[b] para usarla al procesar un evento de botón más tarde.

Tenga en cuenta que, en el siguiente código, assets es un diccionario previamente definido que contiene títulos para botones. En la processButton(self) , self.sender() es igual a una entrada en los buttons[] variable de clase 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 

La salida fue como la siguiente, donde las cuatro primeras líneas se imprimieron durante el bucle for , y las últimas cuatro se imprimieron cuando los cuatro botones se presionaron en orden.

 b[key]=  b-text= K1 b[key]=  b-text= K2 b[key]=  b-text= K3 b[key]=  b-text= K4 sender=  s-text= K1 data[.]= L1 sender=  s-text= K2 data[.]= L2 sender=  s-text= K3 data[.]= L3 sender=  s-text= K4 data[.]= L4 

En Python, las instancias de clase son invocables. Puedes usar una instancia de una clase como una función. Esa clase puede contener lo que quieras. (En algunos lenguajes o marcos, un objeto llamable se llama un functor o un objeto de función ).

 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!