Search code examples
pythonpyqtpyqt4python-2.7signals-slots

Signal-Slot Connection between Creator and Created Class


I have a question.

I have two classes, A and B. A creates object of type B, and also emits signals like this:

QtCore.QObject.emit(QtCore.SIGNAL('mySignal'), "Hello World")

B can see methods in A as A passed 'self' as an argument to the constructor while creating B, as described here.

Now, I want to write a slot in B for that signal emitted in A like this:

self.connect(self._creator, QtCore.SIGNAL('mySignal'), mySlot)

Here I would like to mention that both A and B inherit from QtCore.QObject. The method mySlot is just supposed to print the value it receives as the argument from the signal.

When I run it, I get this error:

QObject.emit(SIGNAL(), ...): first argument of unbound method must have type 'QObject'

In the init() of both the classes, I have added this:

QtCore.QObject.__init__(self)

Without adding this, I get the error:

RuntimeError: underlying C/C++ object has been deleted

I am not experienced in Qt. I do not understand what is going wrong. Please help.


Solution

  • first argument of unbound method must have type 'QObject'

    As error says, you need to pass reference to A for QtCore.QObject.emit or call it with instance method:

    QtCore.QObject.emit(self, QtCore.SIGNAL('mySignal'), "Hello World")
    

    Or

    self.emit(QtCore.SIGNAL('mySignal'), "Hello World")
    

    Fully working example (if I understood you right):

    from PyQt4 import QtCore
    
    class A(QtCore.QObject):
        mySignal = QtCore.SIGNAL('mySignal(QString)')
        def __init__(self):
            QtCore.QObject.__init__(self)
    
        def create_b(self):
            return B(self)
    
        def some_action(self):
            QtCore.QObject.emit(self, QtCore.SIGNAL('mySignal'), "Hello World")
            # this will work too
            self.emit(QtCore.SIGNAL('mySignal'), "Hello World")
    
    class B(QtCore.QObject):
        def __init__(self, creator):
            QtCore.QObject.__init__(self)
            self._creator = creator
            self.connect(self._creator, QtCore.SIGNAL('mySignal'), self.mySlot)
    
        def mySlot(self, str):
            print str
    
    a = A()
    b = a.create_b()
    a.some_action()
    

    Even better solution, is to use New-style Signals and Slots

    Here is example for you case:

    from PyQt4 import QtCore
    
    class A(QtCore.QObject):
        mySignal = QtCore.pyqtSignal(str)
        def __init__(self):
            QtCore.QObject.__init__(self)
    
        def create_b(self):
            return B(self)
    
        def some_action(self):
            self.mySignal.emit("Hello World")
    
    class B(QtCore.QObject):
        def __init__(self, creator):
            QtCore.QObject.__init__(self)
            self._creator = creator
            self._creator.mySignal.connect(self.mySlot)
    
        def mySlot(self, str):
            print str
    
    a = A()
    b = a.create_b()
    a.some_action()