Problem with PyQt5 signals emitted from other classes

593 Views Asked by At

In the example below I want to send a signal from A to Main and from B to Main. Receiving the signal from A is OK, but B does not work. The tricky part is that the "calculations" in B must be triggered from A, not from Main. Will appreciate any help.

Main:

import sys

from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtWidgets import QApplication

from A import A
from B import B


class Main(QObject):
    def __init__(self):
        super(Main, self).__init__()
        self.a = A()
        self.b = B()
        self.a.msg.connect(self.show_message)
        self.b.msg.connect(self.show_message)

    @pyqtSlot(str)
    def show_message(self, text):
        print(text)

    def start(self):
        self.a.dojob()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    m = Main()
    m.start()
    sys.exit(app.exec_())

class A:

from PyQt5.QtCore import pyqtSignal, QObject
from B import B


class A(QObject):
    msg = pyqtSignal(str)

    def __init__(self):
        super(A, self).__init__()
        self.b = B()

    def send_message(self):
        self.msg.emit("from A")

    def dojob(self):
        self.send_message()
        self.b.dojobB()

class B:

from PyQt5.QtCore import pyqtSignal, QObject


class B(QObject):
    msg = pyqtSignal(str)

    def __init__(self):
        super(B, self).__init__()

    def send_message(self):
        self.msg.emit("from B")

    def dojobB(self):
        self.send_message()
1

There are 1 best solutions below

1
On

The problem is that you are thinking that the object b created in Main is the same object b that is created in A but that is false, they are 2 different objects (you can execute print(self.b) in each and you'll see that you get different id).

So there are 2 possible solutions:

  • Do not create an object b in A and pass the object b created in Main to class A through the constructor:
class Main(QObject):
    def __init__(self):
        super(Main, self).__init__()
        self.b = B()
        self.a = A(self.b)
        self.a.msg.connect(self.show_message)
        self.b.msg.connect(self.show_message)
class A(QObject):
    msg = pyqtSignal(str)

    def __init__(self, b):
        super(A, self).__init__()
        self.b = b
  • Or do not create a new object b in Main and connect the signal of the object b created in A
class Main(QObject):
    def __init__(self):
        super(Main, self).__init__()
        self.a = A()
        self.a.msg.connect(self.show_message)
        self.a.b.msg.connect(self.show_message)