4

I am trying to create a custom signal for a QRunnable Object for my PySide2 application. All examples have led me create a signal the following way:

class Foo1(QtCore.QObject):

    def __init__():
        super().__init__()
        self.thread = Foo2()
        self.thread.signal.connect(foo)

    def foo():
        # do something


class Foo2(QtCore.QRunnable):

    signal = QtCore.Signal()

However, I am getting the following error on self.thread.signal.connect(foo):

'PySide.QtCore.Signal' object has no attribute 'connect'

How should I implement a custom signal for a QRunnable object?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

9

A QRunnable is not a QObject so it can not have signals, so a possible solution is to create a class that provides the signals:

class FooConnection(QtCore.QObject):
    foosignal = QtCore.Signal(foo_type)

class Foo2(QtCore.QRunnable):
    def __init__(self):
        super(Foo2, self).__init__() 
        self.obj_connection = FooConnection()

    def run(self):
        # do something
        foo_value = some_operation()
        self.obj_connection.foosignal.emit(foo_value)

class Foo1(QtCore.QObject):
    def __init__():
        super().__init__()
        self.pool = Foo2()
        self.pool.obj_connection.foosignal.connect(foo)
        QtCore.QThreadPool.globalInstance().start(self.pool)

    @QtCore.Slot(foo_type)
    def foo(self, foo_value):
        # do something
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • I have read mixed documentation on whether a class has to inherit from QObject to implement QtCore.Signal. One doc sheet explicitly said QtCore.Signal existed specifically to allow signal creation for classes that did not inherit from QObject (unfortunately I cannot find that docsheet anymore). Are you certain that inheriting from QObject is necessary? – Matthew Spydell Oct 30 '18 at 02:06
  • @MatthewSpydell the signals can only be created in the classes that inherit from QObject, for example the widgets are QObjects, work with Qt in c++ and python and the condition of QObject is mandatory in both. If you have read a tutorial that says otherwise, I recommend that you no longer read it. For example, [the docs](https://wiki.qt.io/Qt_for_Python_Signals_and_Slots) indicate: *Note: Signals should be defined only within classes inheriting from QObject. This way the signal information is added to the class QMetaObject structure.* – eyllanesc Oct 30 '18 at 02:10
  • The are some example on the ufficial documentation https://wiki.qt.io/Qt_for_Python_Signals_and_Slots The last one demostrate something very similar using QThread. – Zompa Jan 29 '20 at 08:10
  • `QRunnable is not a QObject` made my day. Thank you! I though every class that starts with `Q` is a `QObject` – RedEyed Feb 23 '21 at 14:23