Как передать аргументы функциям одним нажатием кнопки в PyQt?

Я хочу передать аргументы функции, когда я нажимаю кнопку. Что я должен добавить к этой строке button.connect(button, QtCore.SIGNAL('clicked()'), calluser(name)), чтобы она передала значение функции:

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

Еще одна вещь, кнопки будут генерироваться с использованием цикла for; поэтому значение name будет меняться. Поэтому я хочу прикрепить каждое имя с помощью кнопки. Я сделал то же самое в Pytk, используя цикл for и вызывая базовую функцию аргумента при нажатии.


person uahmed    schedule 21.07.2011    source источник
comment
вам нужно где-то установить имя переменной .. где это устанавливается?   -  person Tom Studee    schedule 22.07.2011
comment
Метод лямбда работает для меня и поддерживает структуру программы Qt: stackoverflow.com/a/53928495/7944058   -  person Casey    schedule 20.06.2019


Ответы (6)


Вы можете просто написать

name = "user"
button.clicked.connect(lambda: calluser(name))
person ozcanyarimdunya    schedule 23.07.2019
comment
Еще элегантнее! понравилось! - person NinjasAtWork; 31.07.2019
comment
если вышеуказанное не работает (например, внутри цикла), сделайте следующее: button.clicked.connect(состояние лямбда, x=имя: calluser(x)) - person magamig; 22.04.2020
comment
Ваш ответ именно то, что я искал... Большое спасибо! - person SALMAANYEHIA; 14.07.2020

Я попробовал эффективный способ сделать это, и это сработало для меня хорошо. Вы можете использовать код:

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))
person xeon    schedule 22.03.2017
comment
очень элегантно :D - person NinjasAtWork; 31.07.2019
comment
Кто-нибудь действительно пробовал это с несколькими именами перед голосованием? Partial заморозит имя. т.е. как только он установлен для пользователя, вы не можете изменить его через графический интерфейс. - person Julius; 19.07.2021

Обычно GUI создаются с использованием классов. Используя связанные методы в качестве обратных вызовов (см. self.calluser ниже), вы можете «передавать» информацию обратному вызову через атрибуты self (например, self.name):

Например, используя слегка измененный код из этого руководства:

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

Поскольку обратный вызов сам по себе всегда вызывается без дополнительных аргументов, когда вам нужно передать отдельную дополнительную информацию многим обратным вызовам, вам нужно сделать разные обратные вызовы для каждой кнопки.

Поскольку это может быть трудоемко (если делать это вручную), вместо этого используйте фабрику функций. См. пример ниже. Фабрика функций — это замыкание. Ей могут быть переданы дополнительные аргументы, к которым может получить доступ внутренняя функция при вызове:

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_()
person unutbu    schedule 22.07.2011
comment
Спасибо за ответ, но в моем случае значение имени изменится, так как кнопки будут генерироваться циклом for. Итак, могу ли я передать значения в качестве аргументов функции? - person uahmed; 22.07.2011
comment
+1; calluser-Function также может обращаться к любым методам или атрибутам через self.* Это работает там, где лямбда-функции терпят неудачу! - person LuWi; 29.07.2016
comment
@LuWi Знаете ли вы, почему лямбда-функции не работают? - person aoh; 19.01.2018
comment
Я предполагаю, что это как-то связано с прицелами, но я не совсем уверен. Я был рад, что он заработал ;) - person LuWi; 19.01.2018

В Python экземпляры классов можно вызывать. Вы можете просто использовать экземпляр класса как функцию. Этот класс может содержать все, что вы хотите. (В некоторых языках или фреймворках вызываемый объект называется функтором или функциональным объектом.)

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!
person eje211    schedule 04.08.2016

Вот еще один способ. --- PARTIAL -- Я нахожу это наиболее простым:

    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

найдено на: http://tech-artists.org/forum/showthread.php?3118-PyQt-Maya-How-to-pass-arguments-to-a-function-when-connecting-it-to-PyQt-button

person Tomasz Edwin    schedule 18.12.2013
comment
Кажется, это не работает, если входной аргумент изменяется. Например. button.clicked.connect(partial(self.function, self.currentSelection)), если self.currentSelection изменено. Затем вы должны установить аргумент внутри функции через self или создать вложенную функцию. - person komodovaran_; 25.04.2018

Показанный ниже код иллюстрирует метод связывания данных со сгенерированными кнопками. Например, вы можете изменить оператор self.keydata[b] = key, чтобы сохранить кортеж данных в self.keydata[b] для последующего использования при обработке события кнопки.

Обратите внимание, что в следующем коде assets — это ранее определенный словарь, содержащий названия кнопок. В подпрограмме processButton(self) self.sender() равно записи в переменной класса 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

Вывод был примерно следующим: первые четыре строки печатались во время цикла for, а последние четыре печатались, когда четыре кнопки были нажаты по порядку.

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
person James Waldby - jwpat7    schedule 20.04.2016