当前位置: 首页 > 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编译期检查、集中绑定、一行一对最好,所有绑定尽在一处最好,编译期类型安全零额外,编译期展开
http://www.xdnf.cn/news/76789.html

相关文章:

  • 通信与推理的协同冲突与架构解耦路径
  • Linux学习笔记2
  • 常见的HTTP请求报错案例
  • 数据结构*链表- LinkedList
  • 用Go语言正则,如何爬取数据
  • 前端如何优雅地对接后端
  • django之数据的翻页和搜索功能
  • yaml里的挪威问题是啥
  • 从零开始搭建Django博客②--Django的服务器内容搭建
  • 分布式之CAP原则:理解分布式系统的核心设计哲学
  • 【前端】【业务逻辑】 数据大屏自适应方案汇总
  • vs2017中,将CMake构建目录设置在项目目录下
  • Pikachu靶场-RCE漏洞
  • 聊一聊接口服务如何防止被恶意请求
  • HarmonyOS:网络HTTP数据请求
  • 轻量级景好鼠标录制器
  • 爆改 toxml 组件 支持数据双向绑定 解决数据刷新问题
  • 百度搜索 API 相比于爬虫的效率提升、价格及如何注册使用
  • 【MCP Node.js SDK 全栈进阶指南】初级篇(5):MCP提示模板开发
  • 网络协议之详解(Detailed Explanation of Network Protocol)
  • 【创客教育】气压传感器模块
  • 【gpt生成-其二】以go语言为例,详细讲解 并发模型:线程/协程/ Actor 实现
  • Git远程操作
  • 数据库sql语句 中 GROUP BY 关键字详解及字段要求
  • Nacos 2.0.2 在 CentOS 7 上开启权限认证(含 Docker Compose 配置与接口示例)
  • 在Windows上签名苹果APP介绍 - 附CSDN下载地址
  • 卷积神经网络基础(四)
  • 【MATLAB第116期】基于MATLAB的NBRO-XGBoost的SHAP可解释回归模型(敏感性分析方法)
  • Trino分布式 SQL 查询引擎
  • android contentProvider 踩坑日记