Search code examples
qt5signals-slots

Qt5 emit a signal on behalf of another object


Is it possible to emit a signal on behalf of another QObject? the reason I would like to do this is that it would be very useful when writing mock/test code and simply want to simulate that a certain object emitted a signal.

I tried to use

QMetaObject::invokeMethod(otherObject, "mySignal", Q_ARG(QString, myArg));

because the documentation says:

[...] Invokes the member (a signal or a slot name) on the object obj.[...]

But this does not work for me. The signal is simply not emitted.


Solution

  • You can simply invoke the signal through the class like so:

    otherObject.mySignal("Testing!");
    

    Edit

    Good point on the thread-safety issue. I got it to work as well with the invokeMethod solution by explicitly setting the connection type. If your objects are in different threads, you'd need to use the QueuedConnection rather than the DirectConnection. Here is my simple test case:

    main.cpp

    #include <QObject>
    #include "Stub.h"
    
    int main()
    {
        Stub stub;
        Stub2 stub2;
    
        QObject::connect(&stub, &Stub::TestSignal, &stub2, &Stub2::TestReceiver);
        QMetaObject::invokeMethod(&stub, 
                                  "TestSignal", 
                                  Qt::DirectConnection, 
                                  Q_ARG(QString, "myArg"));
    
        return 0;
    }
    

    Stub.h

    #ifndef STUB_H
    #define STUB_H
    
    #include <QObject>
    #include <QDebug>
    
    class Stub : public QObject
    {
        Q_OBJECT
    
    signals:
        void TestSignal(QString s);
    };
    
    class Stub2 : public QObject
    {
        Q_OBJECT
    
    public:
        void TestReceiver(QString s) {qDebug() << "Got s:" << s;}
    };
    
    #endif // STUB_H