PyQt5: How do I “collect” or “receive” an emitted signal?

Tags: , ,



In my code, I have 2 classes in 2 separate files. I have a signal testSignal, a button pushButton and I connected the button like this:

testSignal = QtCore.pyqtSignal()

pushButton.pressed.connect(buttonPressed)

def buttonPressed(self):
    testSignal.emit()

Now what I want to do is “receive” the emitted signal in the class/file, but I’m somewhat in the dark on how emit() actually works. Does anyone have any links for guides for the emit() function or can help somehow?

Thanks

Answer

[Py]Qt signals must be declared at the class level, as they become “active” only whenever a new class instance is created. Also, they can only be used for classes that inherit from QObject (including QWidget subclasses), and using them with standard python object classes will not work.

class SomeWindow(QtWidgets.QWidget):
    testSignal = QtCore.pyqtSignal()
    def __init__(self):
        super().__init__()
        # ...
        pushButton.pressed.connect(self.buttonPressed)
        # connect the custom signal with an *instance method*
        self.testSignal.connect(self.someInstanceFunction)

    def buttonPressed(self):
        # emit the signal
        self.testSignal.emit()

    def someInstanceFunction(self):
        print('hello from the instance!')


def someAnonymousFunction():
    print('hello from outside!')


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = SomeWindow()
    # connect the signal with an anonymous function
    window.testSignal.connect(someAnonymousFunction)
    sys.exit(app.exec_())

Obviously the example above doesn’t make a lot of sense, as custom signals are normally used to communicate between instances of (possibly different) classes, but that’s just for explanation purposes. Also, you could “concatenate” signals (as long as their signature is compatible):

class SomeWindow(QtWidgets.QWidget):
    testSignal = QtCore.pyqtSignal()
    def __init__(self):
        super().__init__()
        # ...
        # emit the testSignal when the button emits its pressed signal
        pushButton.pressed.connect(self.testSignal)
        self.testSignal.connect(self.someInstanceFunction)

    # ...

Note that if you want to do something when the user clicks a button, you should use clicked(), not the pressed() one and the difference is very important: it’s common convention that a button is considered clicked only when the user presses and releases the mouse button while still in the button area, so that the “click” can be avoided if the mouse button is released outside it. If you connect to pressed(), the signal will be emitted as soon as the mouse button is just pressed down on the button, which is not considered a standard behavior.



Source: stackoverflow