如何在PyQt中通过点击按钮向函数传递参数?

55 人关注

我想在点击按钮时将参数传递给一个函数。我应该在这一行添加什么 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循环并在点击时调用参数基函数做了同样的事情。

2 个评论
你需要在某个地方设置变量 "name",它在哪里被设置?
lambda方法对我来说是有效的,并且保持了Qt程序的结构。 stackoverflow.com/a/53928495/7944058
python
function
arguments
pyqt4
argument-passing
uahmed
uahmed
发布于 2011-07-22
7 个回答
ozcanyarimdunya
ozcanyarimdunya
发布于 2022-03-08
已采纳
0 人赞同

你可以简单地写

name = "user"
button.clicked.connect(lambda: calluser(name))
    
更加优雅!喜欢它
如果上面的方法不起作用(例如在一个循环内),可以这样做:button.clicked.connect(lambda state, x=name: calluser(x))
你的答案正是我在寻找的......非常感谢您!
Perfect solution!
@magamig 为什么上面的内容在循环内不能工作?
xeon
xeon
发布于 2022-03-08
0 人赞同

我尝试了一种有效的方法,对我来说效果不错。你可以使用这个代码。

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))
    
非常优雅 :D
有没有人在上调投票前真正试过用多个名字?局部会冻结名字。也就是说,一旦它被设置为 "用户",你就没有办法通过GUI改变它。
unutbu
unutbu
发布于 2022-03-08
0 人赞同

通常,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_()
    
谢谢你的回答,但在我的案例中,名称的值会改变,因为按钮将由for循环产生。所以我可以把这些值作为参数传给函数吗?
LuWi
+1;calluser-Function也可以通过self.*访问任何方法或属性,这在lambda函数失败的情况下是有效的。
aoh
@LuWi 你知道为什么lambda函数会失败吗?
LuWi
我猜这与瞄准镜有关,但我不完全确定。我很高兴能让它工作;)
Tomasz Edwin
Tomasz Edwin
发布于 2022-03-08
0 人赞同

这里有另一种方法。--部分 -- 我发现这个方法最简单。

    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

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

如果输入参数发生变化,它似乎就不工作了。例如: button.clicked.connect(partial(self.function, self.currentSelection)) ,如果 self.currentSelection 被改变。那么你应该在函数内部通过 self 设置参数,或者创建一个嵌套函数。
eje211
eje211
发布于 2022-03-08
0 人赞同

在 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!
    
James Waldby - jwpat7
James Waldby - jwpat7
发布于 2022-03-08
0 人赞同

下面显示的代码说明了一种将数据与生成的按钮相关联的方法。 例如,你可以改变语句 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()] 

输出结果如下,前四行在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
    
MD SHAYON
MD SHAYON
发布于 2022-03-08
0 人赞同

你也可以用参数来做。

button.cliked.connect(lambda self.change_value( "extra"))