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();
};
- 生成连接时把返回值 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 | 编译期检查、集中绑定、一行一对 | 最好,所有绑定尽在一处 | 最好,编译期类型安全 | 零额外,编译期展开 |