当前位置: 首页 > news >正文

Qt信号槽连接的三种方法对比

信号槽连接方法对比

  • 1. 直接连接
  • 2. 集中管理
  • 3.函数指针+初始化列表
    • 后期需要disconnect
  • 对比

1. 直接连接

 connect(codeWindow, &CodeEditorWindow::SetBaseLineSignal, monitoringWindow, &MonitoringWindow::SetBaseLineSlot),connect(&ButtonTree::Instance(), &ButtonTree::Function,
this, &UI::Function),
connect(&ButtonTree::Instance(), &ButtonTree::LeftClicked,
this, &UI::LeftClicked),connect(parSearchdialog, &SearchDialog::SearchRequested, 
parWindow, &ParametersWindow::FocusOnLineEditByIndex),

2. 集中管理

// SignalBinder.h
#ifndef SIGNALBINDER_H
#define SIGNALBINDER_H#include <QObject>
#include <vector>/*** 绑定描述结构:sender, signal, receiver, slot*/
struct SignalBinding {QObject*    sender;const char* signal;QObject*    receiver;const char* slot;
};/*** SignalBinder:批量自动 connect 信号与槽*/
class SignalBinder {
public:/*** 批量绑定所有描述的信号–槽对*/static void bindAll(const std::vector<SignalBinding>& bindings) {for (const auto& b : bindings) {bool ok = QObject::connect(b.sender, b.signal,b.receiver, b.slot);if (!ok) {qWarning("SignalBinder: connect failed %s -> %s", b.signal, b.slot);}}}
};#endif // SIGNALBINDER_H
// UI.cpp
#include "SignalBinder.h"void UI::ConfigSignalsSlot() {// 定义所有待绑定的四元组static const std::vector<SignalBinding> bindings = {{ codeWindow,                 SIGNAL(SetBaseLineSignal(QString)),    monitoringWindow,    SLOT(SetBaseLineSlot(QString)) },{ &ButtonTree::Instance(),    SIGNAL(Function(QString)),             this,                SLOT(Function(QString))       },{ &ButtonTree::Instance(),    SIGNAL(LeftClicked(QString)),          this,                SLOT(LeftClicked(QString))    },{ parSearchdialog,            SIGNAL(SearchRequested(int)),          parWindow,           SLOT(FocusOnLineEditByIndex(int)) },// ... 后续模块只需再添加一行即可};// 一次性完成所有信号–槽绑定SignalBinder::bindAll(bindings);
}

3.函数指针+初始化列表

void UI::ConfigSignalsSlot()
{// 用一个 std::initializer_list 执行所有 connect,返回的 QMetaObject::Connection 会被丢弃// (如果你需要 later disconnect,就把它们保存到成员变量里)[[maybe_unused]] const auto connections = std::initializer_list<QMetaObject::Connection>{// codeWindow::SetBaseLineSignal(QString) -> monitoringWindow::SetBaseLineSlot(QString)connect(codeWindow,&CodeEditorWindow::SetBaseLineSignal,monitoringWindow,&MonitoringWindow::SetBaseLineSlot),// ButtonTree::Function(QString) -> UI::Function(QString)connect(&ButtonTree::Instance(),&ButtonTree::Function,this,&UI::Function),// ButtonTree::LeftClicked(QString) -> UI::LeftClicked(QString)connect(&ButtonTree::Instance(),&ButtonTree::LeftClicked,this,&UI::LeftClicked),// SearchDialog::SearchRequested(int) -> ParametersWindow::FocusOnLineEditByIndex(int)connect(parSearchdialog,&SearchDialog::SearchRequested,parWindow,&ParametersWindow::FocusOnLineEditByIndex),// ……后续所有绑定都放这里即可……};// (void)connections; // 如果编译器抱 unused warning,就这样显式丢弃
}

后期需要disconnect

1.在类里用一个成员容器保存连接句柄

// UI.h
class UI : public QObject {// ...
private:std::vector<QMetaObject::Connection> m_connections;void ConfigSignalsSlot();void disconnectAllSignals();
};
  1. 生成连接时把返回值 push_back 到这个容器
// UI.cpp
void UI::ConfigSignalsSlot()
{// 先断掉旧的disconnectAllSignals();// 然后重新连接,并把每个 QMetaObject::Connection 存下来m_connections.push_back(connect(codeWindow,&CodeEditorWindow::SetBaseLineSignal,monitoringWindow,&MonitoringWindow::SetBaseLineSlot));m_connections.push_back(connect(&ButtonTree::Instance(),&ButtonTree::Function,this,&UI::Function));m_connections.push_back(connect(&ButtonTree::Instance(),&ButtonTree::LeftClicked,this,&UI::LeftClicked));m_connections.push_back(connect(parSearchdialog,&SearchDialog::SearchRequested,parWindow,&ParametersWindow::FocusOnLineEditByIndex));// …如果有更多绑定,继续 push_back…
}

3.断开所有/部分连接

void UI::disconnectAllSignals()
{for (auto& c : m_connections)QObject::disconnect(c);m_connections.clear();
}

对比

方式关键特点可维护性类型安全运行时开销
SIGNAL/SLOT 宏字符串化,运行时匹配较差,需要手动对照无(仅运行时错误)轻微
SignalBinder + 字符串表集中管理,少写重复代码中等,只要维护描述表无(仍是字符串)少量循环开销
函数指针 + initializer_list编译期检查、集中绑定、一行一对最好,所有绑定尽在一处最好,编译期类型安全零额外,编译期展开

相关文章:

  • 开源QML控件:进度条滑动控件(含源码下载链接)
  • 【得物】20250419笔试算法题
  • 高级java每日一道面试题-2025年4月22日-基础篇[反射篇]-如何通过反射创建一个对象实例?
  • ProxySQL 的性能优化需结合实时监控数据与动态配置调整
  • 实验一-密码学数学基础
  • 2025年4月22日(平滑)
  • lvgl 动画设计
  • 【第九章 Python学习之函数Ⅱ】
  • 【汽车ECU电控数据管理篇】S19文件格式解析篇章
  • Java面试实战:谢飞机的求职记 - Spring Boot、Redis与微服务技术问答解析
  • RAG是什么?
  • IDEA下载kotlin-compiler-embeddable特别慢
  • 1.C++ 动态内存分配对比:malloc/free VS new/delete以及 2.nullptr VS NULL 区别
  • python环境使用conda,conda如何升级默认的python版本
  • Spring集合注入Bean
  • 从项目真实场景中理解二分算法的细节(附图解和模板)
  • C++ 快速幂算法
  • 记录学习的第三十天
  • 配置openjdk调试环境
  • AI大模型-window系统CPU版安装anaconda以及paddle详细步骤-亲测有效
  • 外汇局:4月以来外汇市场交易保持平稳,跨境资金延续净流入
  • 【社论】上海车展40年,见证了什么
  • 马上评|遭强奸之后私刑报复,不属正当防卫
  • 哈佛大学就联邦经费遭冻结起诉特朗普政府
  • 郑州卫健委通报郑飞医院“血液净化”问题:拟撤销该院血液净化技术备案
  • 62岁中国国际商会副会长、康力电梯创始人王友林逝世