前言
本文详细介绍 QT 中信号与槽机制的原理、用法、实现方式。
一、QT 信号与槽机制原理
1、什么是信号
信号:信号本质是事件,在 Qt 中信号以函数形式呈现。当特定事件发生时,对象会发出对应的信号。常见触发信号的场景包括:
- 界面元素操作(按钮点击、复选框切换)
- 窗口状态变化(窗口刷新、关闭)
- 系统事件(鼠标移动、键盘输入)
- 数据变化(列表项添加、模型数据更新)
2、什么是槽
槽:槽是用于响应信号的特殊函数,与一般的函数不同,槽函数可以通过connect()
与信号关联。当关联的信号被发射时,槽函数会被自动调用。槽函数需要用户手动实现,其定义方式与普通成员函数类似,但需要使用特定的声明语法。
3、信号与槽连接方式
信号与槽的关联通过QObject::connect()
函数实现,Qt 提供了多种重载形式:
// Qt4风格(基于字符串的连接)
QMetaObject::Connection QObject::connect(
const QObject *sender,
const char *signal,
const QObject *receiver,
const char *method,
Qt::ConnectionType type = Qt::AutoConnection
);
// Qt5风格(基于函数指针的连接)
QMetaObject::Connection QObject::connect(
const QObject *sender,
PointerToMemberFunction signal,
const QObject *receiver,
PointerToMemberFunction method,
Qt::ConnectionType type = Qt::AutoConnection
);
// Lambda表达式连接(Qt5+)
QMetaObject::Connection QObject::connect(
const QObject *sender,
PointerToMemberFunction signal,
const QObject *context,
const Functor &functor,
Qt::ConnectionType type = Qt::AutoConnection
);
其中参数 sender
表示发出信号的对象,参数 signal
表示 sender
对象的信号,参数 receiver
表示信号接收者,参数 method
表示 receiver
对象的槽函数,当检测到 sender
信号, receiver
对象调用 method
方法。第五个参数 type
为Qt::ConnectionType
枚举,里面提供了五种连接类型,默认为AutoConnection
- Qt::AutoConnection(默认值):
AutoConnection
会根据发送者和接收者所在的线程自动选择连接方式。如果信号和槽在同一线程,使用DirectConnection
,如果信号和槽在不同线程,使用QueuedConnection
。大多数情况都直接使用默认值 - Qt::DirectConnection:当信号发射时,槽函数直接执行。槽函数在信号发射者的线程中执行,不会经历事件循环,可能导致线程安全问题。当信号与槽在同一线程并且需要立刻响应时可以使用
DirectConnection
- Qt::QueuedConnection:当信号发射后,槽函数不会立刻执行,会放入接收者线程的事件队列中,等待该线程处理事件时执行。槽函数在接收者的线程中执行,可以避免跨线程直接调用,执行存在一定的延迟。在需要跨线程通信异步执行,需要保持线程安全时可以使用
QueuedConnection
- Qt::BlockingQueuedConnection:类似于
QueuedConnection
,但信号发射后会堵塞当前线程,直到槽函数执行完毕。跨线程同步调用,可能会导致死锁(如果接收者和发送者在同一线程)。在需要等待槽函数执行结果的同步执行跨线程通信时可以使用BlockingQueuedConnection
。 - Qt::UniqueConnection:与其他连接类型组合使用,确保同一对信号和槽之间只建立一次连接。可以避免重复连接导致槽函数被多次调用。
// 1. 默认连接(AutoConnection)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()));
// 2. 直接连接(同一线程内立即执行)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()), Qt::DirectConnection);
// 3. 队列连接(跨线程安全调用)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()), Qt::QueuedConnection);
// 4. 阻塞队列连接(跨线程同步调用)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()), Qt::BlockingQueuedConnection);
// 5. 唯一连接(防止重复连接)
connect(sender, SIGNAL(valueChanged()), receiver, SLOT(updateValue()), Qt::AutoConnection | Qt::UniqueConnection);
信号与支持多种连接方式:
- 一个信号可以与另一个信号相连(信号触发信号)
connect(Object1,SIGNAl(signal1),Object2,SIGNAL(signal1));
- 同一个信号可以与多个槽相连(信号与槽)
connect(Object1,SIGNAl(signal2),Obect2,SIGNAL(slot2));
connect(Object1,SIGNAl(signal2),Object3,SIGNAL(slot1));
- 同一个槽可以响应多个信号
connect(Object1,SIGNAl(signal12),Object2,SIGNAL(slot2));
connect(Object3,SIGNAl(signal12),Object2,SIGNAL(slot2));
- 🚀 个人简介:优快云「博客新星」TOP 10 , C/C++ 领域新星创作者
- 💟 作 者:锡兰_CC ❣️
- 📝 专 栏:【OpenCV • c++】计算机视觉
- 🌈 若有帮助,还请关注➕点赞➕收藏,不行的话我再努努力💪💪💪
更多专栏订阅推荐: