一、Qt 信号连接类型简介
Qt 支持 5 种连接方式,核心有以下几种常用:
类型 | 说明 |
---|---|
Qt::AutoConnection (默认) |
同线程时用 DirectConnection ,跨线程时自动用 QueuedConnection 。但有陷阱,见下。 |
Qt::DirectConnection |
槽函数在发射信号的线程中立即执行(同步调用) |
Qt::QueuedConnection |
槽函数通过事件队列,在目标对象所在线程中异步执行 |
Qt::BlockingQueuedConnection |
类似 QueuedConnection ,但阻塞等待槽执行完成(必须在多线程中使用) |
Qt::UniqueConnection |
加在上面任意连接方式中,防止重复连接(不是独立类型) |
二、信号与槽定义
✅ Qt5 支持老式宏语法:
connect(sender, SIGNAL(clicked()), receiver, SLOT(doSomething()));
✅ Qt6 支持新式函数指针语法:
connect(sender, &QPushButton::clicked, receiver, &MyClass::doSomething);
Qt5 和 Qt6 的 信号与槽机制(Signal-Slot Mechanism) 基本原理是一致的,但 Qt6 做了一些底层优化和语言支持的增强。
三、跨线程信号槽机制定义:
connect(sender, SIGNAL(signalName()), receiver, SLOT(slotName()), Qt::QueuedConnection);
建议显式使用 Qt::QueuedConnection
。
四、跨线程使用信号与槽代码示例
新建一个线程类,用于在子线程定时:
#include <atomic>
#include <chrono>
#include <thread>
#include <QObject>
#include <QThread>
class WorkerThread : public QThread {
Q_OBJECT
public:
WorkerThread(QObject *parent = nullptr) : QThread(parent), mRunning(true) {}
void run() override {
while (mRunning) {
// 这里的定时器是使用 C++ 的 chrono 和 sleep_for
std::this_thread::sleep_for(std::chrono::seconds(3)); // 每隔3秒触发一次
// 执行定时任务
emit timeout(); // 发出定时信号
}
}
void stop() {
mRunning = false;
}
signals:
void timeout(); // 定时器超时信号
private:
bool mRunning; // 控制线程运行的标志
};
创建一个对象和连接信号:
WorkerThread *mWatchdogThread = new WorkerThread;
connect(mWatchdogThread, &WorkerThread::timeout, this, &MCU::watchDogTimeout, Qt::QueuedConnection);
mWatchdogThread->start();
超时后执行槽函数:
void MCU::watchDogTimeout() {
//向串口发数据
}