问题描述
实际工程中经常遇到一种情况:明明将绑定信号绑定到了对应的槽函数上,信号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;
}
总结
内容比较少就不总结了,如果后续遇到别的情况还会再添加上来的。