将参数传递给PyQt的SIGNAL连接

2 投票
3 回答
6387 浏览
提问于 2025-04-18 01:18

可以给PyQt4的信号连接传递参数吗?在我的情况下,我有个按钮,这些按钮在界面上动态创建的菜单是相同的,这取决于用户的输入:

for j in range(0, len(self.InputList)):

    arrow = QtGui.QPushButton(Form)
    arrow.setGeometry(QtCore.QRect(350, 40*(j+3)+15, 19, 23))

    menu = QtGui.QMenu(Form)
    for element in SomeList:
        cb = QtGui.QRadioButton(element,menu)
        ca = QtGui.QWidgetAction(menu)
        ca.setDefaultWidget(cb)
        QtCore.QObject.connect(cb,QtCore.SIGNAL("stateChanged(int)"),self.SomeFunction)
    arrow.setMenu(menu)  

虽然所有按钮的菜单都是一样的,但用户应该能够从任何一个按钮中选择一个值,对于每个按钮,执行的动作都是一样的(“将选中的值添加到一个文本框”),唯一的区别是这个文本框可能是第个、第个或第个。

我想问的是,是否有办法在这里传递一个参数j

QtCore.QObject.connect(cb,QtCore.SIGNAL("stateChanged(int)"),self.SomeFunction(j))

例子

在这个执行过程中,用户输入的是3,所以我会有3个文本框和3个按钮,菜单都是一样的:

Line Edit 1:
Line Edit 2:
Line Edit 3:

使用同一个函数SomeFunction,我想编辑文本框的值。所以如果用户点击的是第二个文本框的菜单,函数SomeFunction就应该被调用,参数是2 SomeFunction(2),这样同一个方法就能知道哪个文本框是正确的:

Line Edit 1:
Line Edit 2: modified
Line Edit 3: 

我需要这样做,因为主窗口中的文本框数量取决于用户的选择。我是个新手,到目前为止我总是为GUI中的每个对象创建一个函数,但这次数量是动态的,我相信还有更优雅的方法来创建这种信号连接,但到现在为止我从文档中还没有理解这些。

3 个回答

1

我觉得这应该能帮到你。

self.op = "point"
QtCore.QObject.connect(self.radioButton, QtCore.SIGNAL("clicked(bool)"),lambda : self.anyButton(self.radioButton.isChecked(),self.op))

def anyButton(self,kol,vv):
    print kol
    print vv

输出结果是

>>> 
True
point

你可以看看这个链接:PyQt在连接信号时如何向槽发送参数

2

请注意,你正在使用PyQt中一个已经不再推荐使用的SIGNAL/SLOT实现方式,这种方式在PyQt5中已经被移除(而且在PyQt4中的当前实现也有点问题)。

如果可以的话,我建议你改用新的SIGNAL/SLOT语法。

新的信号/槽机制是这样工作的:

class Worker(QThread):
    stateChanged = Signal(int)

    ....

    def some_method(self):
        self.stateChanged.emit(1)

在GUI线程中,你会有类似这样的代码(假设worker = Worker()在某个地方已经定义过):

class GUI(QDialog)

    worker = Worker()

    def __init__(self, parent=None):
        super(GUI, self).__init__(parent)
        self.worker.stateChanged.connect(self.my_desired_method)

    def my_desired_method(self, param):
        print param #prints out '1'

当然,这段代码不能直接使用,但它展示了在PyQt(和PySide)中如何处理信号和槽的基本概念。

2

这里有一种不同的方法:与其把数据作为参数传给信号处理函数,不如把它直接附加到菜单项上。这样做的好处是灵活性更高,因为数据不再隐藏在一个匿名函数里,应用程序的任何部分都可以访问这些数据。

实现起来也非常简单,因为Qt已经提供了所需的接口。下面是如果你采用这种方法,你的示例代码会是什么样子的:

        for j in range(0, len(self.InputList)):

            arrow = QtGui.QPushButton(self)
            arrow.setGeometry(QtCore.QRect(350, 40*(j+3)+15, 19, 23))

            menu = QtGui.QMenu(self)
            group = QtGui.QActionGroup(menu)
            for element in SomeList:
                action = menu.addAction(element)
                action.setCheckable(True)
                action.setActionGroup(group)
                action.setData(j)
            arrow.setMenu(menu)

            group.triggered.connect(self.SomeFunction)

    def SomeFunction(self, action):
        print(action.data())

撰写回答