Search code examples
c++qtsignals-slots

Qt signals and slots in different classes


I have a class X with a slot, and a class Y with a signal. I'm setting up the connection from class X, and created a public method in class Y to emit the signal from class X (I'm not sure this step was necessary).

Then, if I call that method from class X, signal is emitted, and slot is executed. But if I emit signal from class Y, slot is never executed and I don't understand why.

May I stablish connection also at class Y?

This pseudo-code tries to explain what I want:

class X  : public QWidget {
    Q_OBJECT

X(){
    connect(Y::getInstance(), SIGNAL(updateSignal(int)), this, SLOT(updateStatus(int)));
    Y::getInstance().emitSignal(someValue); // Works
}

public slots:
    void updateStatus(int value);

}

class Y : public QObject {

Q_OBJECT

Y(){

}

public:
    Y getInstance();
    void emitSignal(int value) { 
        emit updateSignal(value);
    }


signal:
    void updateSignal(int value);
}

class Z : public Y {
Z(){

}

init(){
 emitSignal(someValue); // Doesn't work
}
}

Solution

  • Remember that connections are not between classes, but between instances. If you emit a signal and expect connected slots to be called, it must be emitted on an instance on which the connection was made. That's your problem.

    Assuming Y is a Singleton:

    If you do connect( Y::getInstance(), ... )

    and Y::getInstance() does new Y() at some point, then the constructor of Y is called before the connection is set up. Like that, the signal will be emitted but the slot will not listen to it yet.

    Apart from that, it would be best to do one of the following things, though you could not emit the signal in the constructor of Y with these approaches:

    • Use a third class Z that knows both X and Y, and do the connection there
    • Dependency Injection. That means X gets an instance of Y in its constructor:

    Example for a Dependency Injection Constructor:

    X::X( Y* const otherClass )
    {
        connect( otherClass, SIGNAL( ... ), this, SLOT( ... )
    }