Search code examples
pythonpyqtpyqt4pyqt5

How to use Slot+Signal in different classes?


I must say it is a very beginner's question. I have read and tried a lot, but still don't understand how Slot+Signal work.

In my following code I want to transfer three variables from MyApp Class into Worker Class, when the button is clicked.

The code does not work.

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys


class Worker(QObject):
    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)

    @pyqtSlot(str, str, int)
    def onJob(self, strA, strB, int1):
        print(strA, strB, int1)
        for i in range(40):
            print(i)


class MyApp(QWidget):
    def __init__(self, parent= None):
        super(MyApp, self).__init__(parent)
        self.initUI()

    def initUI(self):
        self.btn = QPushButton("start", self)
        self.btn.clicked.connect(self.start)
        self.show()

    def start(self):
        otherClass = Worker()
        self.signal = pyqtSignal(str, str, int)
        self.signal.emit("foo", "baz", 10)
        self.signal.connect(otherClass.onJob)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

Solution

  • Your code has the following errors:

    • A signal must not be declared in any method of the class, it must be on the same level as the methods.

    • If I send a signal before connecting it to any slot then nobody will listen to the information so the data will be lost, that is, the transmission of data is almost instantaneous.

    In the following code I have implemented the necessary modifications to make it work:

    class MyApp(QWidget):
        signal = pyqtSignal(str, str, int)
        def __init__(self, parent= None):
            super(MyApp, self).__init__(parent)
            self.initUI()
    
        def initUI(self):
            self.btn = QPushButton("start", self)
            self.btn.clicked.connect(self.start)
            self.show()
    
        def start(self):
            otherClass = Worker()
            self.signal.connect(otherClass.onJob)
            self.signal.emit("foo", "baz", 10)