Passing argument to PyQt SIGNAL connection

喜你入骨 提交于 2019-12-24 04:07:12

问题


Is it possible to pass an argument to PyQt4 Signal connections? In my case I have n buttons with set the same menu dinamically created on the interface, depending on user's input:

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)  

Although the menu is the same for all the buttons into the interface, the user should be able to select a value from any of the buttons and, for any of them, the action is the same ("add the selected value to a line edit") with the only difference that the line edit might be the 1st as well as the 2nd, the 3rd.

What I would like to ask, then, is if there's any way to pass an argument j here:

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

EXAMPLE:

At this execution the user's inputs are 3, so I will have 3 line edits and three push buttons with the same menu:

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

Using the same function SomeFunction, I'd like to edit the value of the Line Edits. So if the user is touching the menu attached to the 2nd line edit, the function SomeFunction shall be called with the argument 2 SomeFunction(2), so the same method will understand itself which Line Edit is the right one:

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

I need this because the number of Line Edits on the main window depends on what the user is selecting. I'm a newbie and so far I've always created one function for any object into the GUI, but this time the number is dynamic and I'm sure there are some more elegant ways to create this kind of signal connections, that I have not understood though so far from my documentations reading.


回答1:


Here is a different approach: instead of attaching the data as an argument to the signal handler, attach it to the menu-item itself. This offers much greater flexibility, because the data is not hidden inside an anonymous function, and so can be accessed by any part of the application.

It is very easy to implement, because Qt already provides the necessary APIs. Here is what your example code would look like if you took this approach:

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



回答2:


Be advised that you are using a deprecated version of SIGNAL/SLOT implementation in PyQt that has been removed in PyQt5 (and even its current implementation in PyQt4 is somewhat buggy).

If possible, I would change the SIGNAL/SLOT syntax in your code.

The way the new Signal/Slot mechanism works is this:

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

    ....

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

In the GUI thread, you would similarly have something like this (assuming worker = Worker() is defined somewhere:

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'

Of course, this code wouldn't work "out of the box", but it's a general concept of how Signals/Slots should be handled in PyQt (and PySide).




回答3:


I think this should help.

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

The output is

>>> 
True
point

you can take a look at this : PyQt sending parameter to slot when connecting to a signal



来源:https://stackoverflow.com/questions/22856614/passing-argument-to-pyqt-signal-connection

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!