1. 基本概念
信号(signals):当对象的状态发生变化或发生特定事件时,自动触发的通知。比如PushButton常见的信号是clicked()信号。
槽:吸收信号并执行逻辑的成员函数。可定义在类的任何部分(public、private、protected)
连接:通过QObject::connect将信号与槽绑定。connect(sender, &Sender::signal, receiver, &Receiver::slot);
2. 四种方法实现
(1)右击控件 → 转到槽(自动天生槽函数)
Qt Creator 自动天生槽函数声明和实现,并在代码中创建连接。
- // 自动生成槽函数声明(头文件中)
- private slots:
- void on_pushButton_close_clicked();
- // 自动生成槽函数实现(源文件中)
- void OnlineMusicWidget::on_pushButton_close_clicked()
- {
- close();
- }
复制代码 (2)connect函数 + 宏(旧版本)
使用 SIGNAL() 和 SLOT() 宏定义信号和槽。通过字符串匹配信号和槽,运行时解析。
- connect(
- ui->pushButton,
- SIGNAL(clicked()),
- this,
- SLOT(handleButtonClick())
- );
- // 槽函数声明
- public slots:
- void handleButtonClick();
复制代码- connect(p_PlayerObject,SIGNAL(positionChanged(qint64)),this,SLOT(HandleLCDNumerTimeChangeFunc(qint64)));
- connect(p_PlayerObject,SIGNAL(positionChanged(qint64)),this,SLOT(HandlePositionChangeFunc(qint64)));
- connect(p_PlayerObject,SIGNAL(durationChanged(qint64)),this,SLOT(HandleProgressTimeChangeFunc(qint64)));
- // 槽函数声明
- private slots:
- void HandleProgessTimeChangeFunc(qint64 dration);
- void HandlePositionChangeFunc(qint64 position);
- void HandleLCDNumberTimeChangeFunc(qint64 duration);
复制代码 (3)connect 函数 + 地址(新版本)
使用&类名::信号 和 &类名::槽直接引用函数地址。编译时静态绑定,类型安全。
- connect(
- ui->pushButton,
- &QPushButton::clicked,
- this,
- &MainWindow::handleButtonClick
- );
- // 槽函数声明
- public slots:
- void handleButtonClick();
复制代码- connect(
- p_PlayerObject, // 发送信号的对象(例如 QMediaPlayer 实例)
- &QMediaPlayer::durationChanged, // 信号(当媒体时长变化时触发)
- this, // 接收槽函数的对象(当前类的实例)
- &MyClass::HandleProgressTimeChangeFunc // 槽函数(处理时长变化的函数)
- );
- connect(p_PlayerObject, &QMediaPlayer::durationChanged, this, &OnlineMusicWidget::HandleProgressTimeChangeFunc);
复制代码 (4)Lambda 表达式(简化槽函数)
使用 Lambda 表达式直接处置惩罚信号逻辑。将槽函数更换为匿名函数,无需显式定义槽。
- // 自动生成槽函数声明(头文件中)
- private slots:
- void on_pushButton_close_clicked();
- // 自动生成槽函数实现(源文件中)
- void OnlineMusicWidget::on_pushButton_close_clicked()
- {
- close();
- }// 使用 Lambda 连接点击信号 connect( pushButton_close, // 发送信号的对象 &QPushButton::clicked, // 信号 this, // 吸收者(当前窗口) [this]() { // Lambda 表达式(槽函数) close(); // 关闭当前窗口 } );
复制代码 方法类型安全编译查抄灵活性适用场景转到槽是是低快速原型开辟connect + 宏否否中Qt 4 兼容或动态连接connect + 地址是是高新项目、类型安全要求高Lambda 表达式是是高简单逻辑、制止定义槽函数 3. 技术细节
(1)信号与槽的元对象系统:
moc(元对象编译器):
- Qt 的moc(元对象编辑器)工具会处置惩罚全部包含 Q_OBJECT 宏的类,天生 moc_*.cpp 文件。
- 这些文件包含信号的实现和槽的元信息,使运行时动态连接。
元方法(Meta-Method):
- 通过 QMetaObject 可以动态访问信号和槽:
- const QMetaObject *meta = sender->metaObject();
- int signalIndex = meta->indexOfSignal("valueChanged(int)");
- int slotIndex = meta->indexOfSlot("handleValue(int)");
- QMetaObject::connect(sender, signalIndex, receiver, slotIndex);
复制代码 (2)信号的重载处置惩罚
强制类型转换解决重载歧义
- // 假设信号有重载:void valueChanged(int) 和 void valueChanged(QString)
- connect(
- sender,
- static_cast<void (SenderClass::*)(int)>(&SenderClass::valueChanged),
- receiver,
- &ReceiverClass::handleIntValue
- );
复制代码 (3)信号与槽的返回值
- 信号无返回值:全部信号必须返回 void。
- 槽可以有返回值,但通常不推荐
4. 高级用法
(1)信号与信号连接
- 信号转发:一个信号触发另一个信号,用于抽象或代理。
- connect(
- button, &QPushButton::clicked,
- this, &MainWindow::startProcessingSignal
- );
复制代码 (2)跨线程通讯(QueuedConnection)
- connect(
- workerThread, &Worker::resultReady,
- mainThread, &MainWindow::updateUI,
- Qt::QueuedConnection
- );
复制代码 (4)Lambda 表达式进阶
- int threshold = 100;
- connect(
- slider, &QSlider::valueChanged,
- [threshold, this](int value) {
- if (value > threshold) this->alert();
- }
- );
复制代码
- connect(
- spinBox, QOverload<int>::of(&QSpinBox::valueChanged),
- [](int value) { qDebug() << "Value:" << value; }
- );
复制代码 4. 底层原理
(1)信号的本质
- 信号是普通函数:由 moc 天生,内部调用 QMetaObject::activate。
(2)槽的调用机制
- 直接连接(DirectConnection):立即在发送者线程调用槽函数。
- 队列连接(QueuedConnection):将槽调用封装为事件,投递到吸收者线程的事件循环。
(3)事件循环与信号槽
- 信号槽依赖事件循环:队列连接和跨线程通讯需要运行 QCoreApplication::exec()。
- 无事件循环的场景(如纯计算线程),需谨慎使用队列连接。
5. 实际案例
(1)动态界面更新
- // 根据数据变化动态更新多个 UI 控件
- connect(
- dataModel, &DataModel::dataChanged,
- this, [this](int index) {
- updateChart(index);
- updateTable(index);
- logChange(index);
- }
- );
复制代码 (2)异步任务链
- // 链式异步操作(下载 → 解析 → 显示)
- connect(
- downloader, &Downloader::finished,
- parser, &DataParser::parse,
- Qt::QueuedConnection
- );
- connect(
- parser, &DataParser::parsed,
- this, &MainWindow::showResult,
- Qt::QueuedConnection
- );
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |