Qt信号槽函数

[复制链接]
发表于 2025-10-5 19:50:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Qt 中的信号(Signals)详解

Qt 的信号与槽(Signals & Slots)机制是其焦点特性之一,用于实现对象间的松耦合通讯。信号与槽允许一个对象在特定变乱发生时关照其他对象,而无需知道罗致者的具体信息。以下是信号的具体剖析:

​一、信号的根本概念


  •         ​信号(Signal)​

    • 由类中的 signals 地域声明的特别成员函数,​无实当代码。
    • 当对象状态变革或变乱发生时,通过 emit 关键字触发信号。
    • 示例:       
      1. class Counter : public QObject {
      2.     Q_OBJECT
      3. public:
      4.     Counter() : m_value(0) {}
      5.     void increment() {
      6.         m_value++;
      7.         emit valueChanged(m_value); // 触发信号
      8.     }
      9. signals:
      10.     void valueChanged(int newValue); // 信号声明
      11. private:
      12.     int m_value;
      13. };
      复制代码
           
  •         ​槽(Slot)​

    • 平凡的成员函数,用于相应信号。
    • 需在类声明中使用 slots 修饰符(Qt4/Qt5 兼容),或直接声明为公有函数(Qt5 支持)。
    • 示例:       
      1. class Display : public QObject {
      2.     Q_OBJECT
      3. public slots:
      4.     void updateDisplay(int value) {
      5.         qDebug() << "当前值:" << value;
      6.     }
      7. };
      复制代码
           
  •         ​毗连(Connection)​

    • 通过 QObject::connect() 将信号与槽绑定。
    • 语法(Qt5 风格):       
      1. connect(sender, &Sender::signal, receiver, &Receiver::slot);
      复制代码
           
                第一个参数是发送对象,第二参数是信号范例 ,第三个是信号罗致者,第四个是收到信 号时调用的槽函数。

​二、信号与槽的底层原理


  •         ​元对象体系(Meta-Object System)​

    • 依靠 Qt 的元对象编译器(moc)天生 moc_*.cpp 代码。
    • 信号和槽的声明需包罗 Q_OBJECT 宏,以启用元对象功能(如动态属性、反射)。
           
  •         ​信号触发过程

    • 当调用 emit signal() 时,Qt 通过元对象体系查找全部毗连的槽。
    • 槽的调用方式取决于毗连范例(直接毗连或队列毗连)。
    • 示例代码天生(简化):       
      1. // moc 生成的代码(伪代码)
      2. void Counter::valueChanged(int newValue) {
      3.     QMetaObject::activate(this, &staticMetaObject, 0, &newValue);
      4. }
      复制代码
           
  •         ​毗连范例

    • ​**Qt::AutoConnection(默认)​**:主动选择直接或队列毗连(根据线程关系)。
    • ​**Qt:irectConnection**:立刻在发送者线程调用槽(同步)。
    • ​**Qt:ueuedConnection**:将槽调用封装为变乱,由罗致者线程处理惩罚(异步)。
    • ​**Qt::BlockingQueuedConnection**:类似队列毗连,但发送者线程会等候槽实行完成。
           
​三、信号与槽的使用方法


  •         ​根本毗连示例
    1. Counter *counter = new Counter;
    2. Display *display = new Display;
    3. // 连接信号与槽
    4. QObject::connect(counter, &Counter::valueChanged, display, &Display::updateDisplay);
    5. // 触发信号
    6. counter->increment(); // 输出:当前值:1
    复制代码
  •         ​Lambda 表达式作为槽
    1. connect(counter, &Counter::valueChanged, [](int value) {
    2.     qDebug() << "Lambda 处理:" << value;
    3. });
    复制代码
  •         ​信号与信号的毗连
    1. QPushButton *button = new QPushButton;
    2. connect(button, &QPushButton::clicked, counter, &Counter::increment);
    复制代码
  •         ​断开毗连
    1. disconnect(counter, &Counter::valueChanged, display, &Display::updateDisplay);
    复制代码

​四、高级用法


  •         ​跨线程通讯
            使用 Qt:ueuedConnection 安全地在差别线程间通报数据:
    1. // 在工作线程触发信号
    2. class Worker : public QObject {
    3.     Q_OBJECT
    4. signals:
    5.     void resultReady(const QString &data);
    6. };
    7. // 主线程接收数据
    8. QThread workerThread;
    9. Worker *worker = new Worker;
    10. worker->moveToThread(&workerThread);
    11. QObject::connect(worker, &Worker::resultReady, mainWindow, &MainWindow::handleResult, Qt::QueuedConnection);
    12. workerThread.start();
    复制代码
  •         ​携带额外参数
            信号和槽的参数可以不完全匹配,但需满足范例兼容性:
    1. signals:
    2.     void progress(int percent, const QString &status);
    3. // 槽函数仅接收部分参数
    4. connect(worker, &Worker::progress, ui->progressBar, &QProgressBar::setValue);
    复制代码
  •         ​QSignalMapper(旧版Qt)​
            用于将多个信号映射到同一槽并携带标识(Qt5 后保举使用 Lambda 替换):
    1. QSignalMapper *mapper = new QSignalMapper;
    2. connect(button1, &QPushButton::clicked, mapper, &QSignalMapper::map);
    3. mapper->setMapping(button1, 1);
    4. connect(mapper, &QSignalMapper::mappedInt, this, &MyClass::handleButton);
    复制代码

​五、信号与变乱的区别

​特性​信号与槽​变乱​触发方式显式调用 emit由体系或 Qt 变乱循环主动触发​用途对象间的业务逻辑通讯处理惩罚底层输入、绘图、定时器等体系变乱​传播机制一对一或一对多毗连可冒泡到父对象或被变乱过滤器拦截​线程安全支持跨线程(通过队列毗连)需手动处理惩罚线程间变乱通报
​六、常见标题与调试


  •         ​信号未触发

    • 查抄 connect 是否乐成(返回 true)。
    • 确保信号已正确声明在 signals 地域,且类包罗 Q_OBJECT 宏。
           
  •         ​槽未实行

    • 确认罗致者对象未被提前烧毁。
    • 查抄毗连范例(如跨线程需使用队列毗连)。
           
  •         ​内存走漏

    • 克制循环引用(如对象相互毗连但未断开)。
    • 使用 QPointer 或智能指针管理罗致者生命周期。
           
  •         ​性能优化

    • 淘汰高频信号(如实时数据更新)的槽处理惩罚耗时。
    • 归并多个信号为单一参数布局体。
           

​七、总结

Qt 的信号与槽机制通过元对象体系实现高效的对象间通讯,具有以下上风:

  • ​松耦合:发送者无需知道罗致者的存在。
  • ​范例安全:编译时查抄参数范例。
  • ​跨线程支持:简化多线程编程。
实用场景:

  • 用户界面交互(如按钮点击相应)。
  • 模块间数据通报(如网络哀求结果回传)。
  • 异步任务状态关照(如进度更新)。
通过公道使用信号与槽,可以构建清晰、可维护的 Qt 应用步调架构。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表