Qt 信号槽入门
核心概念
信号槽是 Qt 最核心的通信机制,替代传统回调函数。
对象 A 对象 B
│ │
│ emit signal(data) │
│─────────────────────────→│ slot(data)
│ │
信号发出者 槽接收者
不需要知道谁在听 不需要知道谁发的
connect 的五种写法
// ① Qt4 风格(字符串匹配,编译期不检查 → 不推荐)
connect(sender, SIGNAL(valueChanged(int)),
receiver, SLOT(onValueChanged(int)));
// ② 函数指针(编译期类型检查 → 推荐)
connect(sender, &Sender::valueChanged,
receiver, &Receiver::onValueChanged);
// ③ Lambda(最灵活)
connect(sender, &Sender::valueChanged,
[](int val) { qDebug() << val; });
// ④ Lambda + this 捕获
connect(button, &QPushButton::clicked, this, [this]() {
m_label->setText("clicked");
});
// ⑤ 信号连接信号
connect(obj1, &Obj1::signalA, obj2, &Obj2::signalB);
连接类型
connect(a, &A::sig, b, &B::slot,
Qt::AutoConnection); // 默认:同线程直调,跨线程排队
connect(a, &A::sig, b, &B::slot,
Qt::DirectConnection); // 当场调用(发射线程中执行槽)
connect(a, &A::sig, b, &B::slot,
Qt::QueuedConnection); // 排队到接收者线程执行
connect(a, &A::sig, b, &B::slot,
Qt::BlockingQueuedConnection); // 跨线程同步调用(发射者等槽执行完)
| 类型 | 执行线程 | 使用场景 |
|---|---|---|
| Auto | 自动判断 | 默认,大多数情况 |
| Direct | 发射者线程 | 同线程,实时性要求高 |
| Queued | 接收者线程 | 跨线程(必须用这个) |
| BlockingQueued | 接收者线程 | 跨线程同步调用 |
自定义信号槽
class Worker : public QObject {
Q_OBJECT // ⚠️ 必须加这个宏
public:
void doWork() {
emit progressChanged(50); // 发射信号
emit finished("done");
}
signals: // 信号:只声明,不实现
void progressChanged(int percent);
void finished(const QString &result);
public slots: // 槽:需要实现
void start() {
doWork();
}
};
注意事项
// ❌ 信号和槽的参数类型必须兼容(槽参数可以比信号少)
connect(s, &S::sig(int, string), r, &R::slot(string)); // ❌ 类型不匹配
// ✅ 槽可以忽略尾部参数
connect(s, &S::sig(int, string), r, &R::slot(int)); // ✅ 只用第一个
// ❌ 同一个 connect 重复调用 → 槽被多次触发
// ✅ 用 Qt::UniqueConnection 防止重复
connect(s, &S::sig, r, &R::slot, Qt::UniqueConnection);
// disconnect 断开连接
disconnect(s, &S::sig, r, &R::slot);