QT中信号槽机制问题:绑定了对应的信号和槽,emit了信号,但槽函数没有触发

849 阅读2分钟

问题描述

实际工程中经常遇到一种情况:明明将绑定信号绑定到了对应的槽函数上,信号emit时,却触发不了槽函数。

解决方法

这个问题可能是两个情况(笔者遇到的)。

1.线程问题

信号和槽可能不在同一线程中,这时候需要选择合适的连接类型。QT中提供了以下连接类型:

//qnamespace.h line1336:
    enum ConnectionType {
        AutoConnection,
        DirectConnection,
        QueuedConnection,
        BlockingQueuedConnection,
        UniqueConnection =  0x80
    };

简单介绍:
1. AutoConnection: 默认连接类型。Qt 根据信号和槽是否在同一线程中自动选择合适的连接类型。如果信号和槽在同一线程中,使用 DirectConnection;如果在不同线程中,使用 QueuedConnection

2. DirectConnection:直接调用:信号发射时,如果槽在同一线程中,会直接调用槽函数。这种方式适用于在同一线程中的场景,避免了线程间通信的开销。

3. QueuedConnection:事件队列:信号发射时,如果槽在不同线程中,信号会被放入槽所在线程的事件队列中,槽函数会在槽所在线程的事件循环中被调用。这种方式适用于跨线程通信。

4. BlockingQueuedConnection:阻塞等待:信号发射时,如果槽在不同线程中,发射信号的线程会阻塞,直到槽函数执行完成。这种方式适用于需要等待槽函数完成后再继续执行的场景,但会带来较大的性能开销。

5. UniqueConnection: 唯一连接:用于确保一个信号只能连接到一个槽函数。这是一个标志,通常与其他连接类型一起使用(例如 AutoConnection | UniqueConnection)。

使用实例:

connect(aEntity, &AEntity::SendCalibrateSigParam, this, &AWorkspace::RecvCalibrateSignal, Qt::QueuedConnection);
connect(this, &AWorkspace::PopMsgBox, this, &AWorkspace::PopWarning, Qt::DirectConnection);

触发不了槽函数,可以尝试更换信号槽连接时的连接类型。说不定就可以了

2.自定义类问题

默认情况下,Qt 的元对象系统(用于信号和槽机制)不认识自定义类型,如果你的信号槽中使用到了自定义类了,就需要将该类注册到 Qt 的元对象系统。例如:

//.h
signals:
    void Update(int chnId, QSharedPointer<double> value1, QSharedPointer<double> value2);

private slots:
    void Recv(int chnId, QSharedPointer<double> value1, QSharedPointer<double> value2);

//main.cpp
int main(){
    
    //......
    //注册自定义类到Qt 的元对象系统。
    qRegisterMetaType<QSharedPointer<double>>("QSharedPointer<double>");
    //此时绑定信号槽,槽函数才会触发
    connect(aEntity, &AEntity::Update, aWorkspace, &AWorkspace::Recv);
    //......
    
    return 0;
}
    

总结

内容比较少就不总结了,如果后续遇到别的情况还会再添加上来的。