【问题标题】:Qt5 emit a signal on behalf of another objectQt5 代表另一个对象发出信号
【发布时间】:2014-03-24 00:46:20
【问题描述】:

是否可以emit 一个signal 代表另一个QObject?我想这样做的原因是它在编写模拟/测试代码并且只是想模拟某个对象发出信号时非常有用。

我尝试使用

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

因为documentation 说:

[...] 调用对象 obj.[...] 上的成员(信号 或插槽名称)。[...]

但这对我不起作用。信号根本没有发出。

【问题讨论】:

    标签: qt5 signals-slots


    【解决方案1】:

    您可以像这样简单地通过类调用信号:

    otherObject.mySignal("Testing!");
    

    编辑

    关于线程安全问题的要点。通过显式设置连接类型,我让它与 invokeMethod 解决方案一起工作。如果您的对象在不同的​​线程中,则需要使用 QueuedConnection 而不是 DirectConnection。这是我的简单测试用例:

    ma​​in.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
    

    【讨论】:

    • 嗯,重点是我不知道有多少其他对象订阅了原始信号。因此,我不会跟踪所有这些,而是​​只模拟一个发射,让一切照常运行。
    • 这不会实现您的目标吗?根据您的 invokeMethod 示例,在我看来,您对需要发出信号的对象有一个引用。我的解决方案只是告诉引用的对象发出信号。
    • 如果是这样,那么线程安全呢?例如,在我的对象在另一个线程的事件循环中运行的情况下?在那种情况下,人们会期望 invokeMethod 工作,但它没有(至少对我来说)。
    • 哇!你真的加紧了挑战!这就是 S.O.由..制作;很棒的答案。非常感谢。 +1 并被接受。
    • 顺便说一句,您声明应该在您的答案中选择 QueuedConnection,但在示例代码中您仍然有 DirectConnection。同样在 Stub2 中,您没有将 TestReceiver 指定为插槽。
    猜你喜欢
    • 1970-01-01
    • 2013-02-17
    • 2019-07-31
    • 1970-01-01
    • 2017-01-03
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多