Qt多窗口架构设计需求简介
Qt多窗口架构设计需求简介
本项目基于Qt框架设计一套企业级低耦合多窗口交互架构,旨在解决传统Qt多窗口开发中窗口耦合严重、页面通信混乱、数据交互困难、扩展维护成本高的问题。通过合理运用多种经典设计模式,实现窗口统一管理、解耦通信、安全数据交互与灵活页面切换,满足实际商用项目的开发需求。
本次架构设计的核心需求如下:
1.窗口统一规范化管理
定义统一窗口抽象接口,约束所有子窗口的标准化实现,配合全局窗口管理器完成窗口自动注册、统一收录与实例查询,杜绝窗口实例散乱、内存管理混乱的问题。
2.支持跨窗口双向数据交互
实现任意窗口之间互相访问实例、调用成员函数、读写控件数据,支持同步直接调用方式,满足即时数据读写、界面联动更新的业务场景。
3.实现解耦式信号通信
搭建全局信号消息中心,基于观察者模式实现异步跨窗口信号槽通信,支持传递文本、自定义结构体等复杂业务对象,实现窗口间完全解耦的事件通知与数据推送。
4.支持页面灵活切换
通过堆栈窗口容器实现多页面无缝切换,主窗口统一管控所有子页面展示逻辑,界面结构清晰、切换流畅。
5.高可扩展、低耦合、易维护
架构遵循面向对象设计思想,结合单例、中介者、注册、接口抽象等设计模式,新增窗口无需修改原有代码,满足项目迭代扩展需求,代码规范性与复用性符合企业级开发标准。
完整 Qt 工程文件(全套复制即用)
1. 项目文件:MultiWindow.pro
qmake
QT += core gui widgets TARGET = MultiWindowDemo TEMPLATE = app SOURCES += \ main.cpp \ MainWindow.cpp \ Window1.cpp \ Window2.cpp \ WindowManager.cpp \ SignalCenter.cpp HEADERS += \ IWindow.h \ MainWindow.h \ Window1.h \ Window2.h \ WindowManager.h \ SignalCenter.h \ UserInfo.h2. 接口:IWindow.h
cpp
运行
#ifndef IWINDOW_H #define IWINDOW_H #include <QString> class IWindow { public: virtual ~IWindow() = default; virtual QString windowName() = 0; }; #endif3. 窗口管理器:WindowManager.h + .cpp
WindowManager.h
cpp
运行
#ifndef WINDOWMANAGER_H #define WINDOWMANAGER_H #include <QObject> #include <QMap> #include "IWindow.h" class WindowManager : public QObject { Q_OBJECT public: static WindowManager* instance(); void registerWindow(IWindow* window); IWindow* getWindow(const QString& name); template <typename T> T* getWindowT(const QString& name) { return dynamic_cast<T*>(getWindow(name)); } private: explicit WindowManager(QObject *parent = nullptr); static WindowManager* m_instance; QMap<QString, IWindow*> m_windowMap; }; #endifWindowManager.cpp
cpp
运行
#include "WindowManager.h" WindowManager* WindowManager::m_instance = nullptr; WindowManager* WindowManager::instance() { if (!m_instance) m_instance = new WindowManager; return m_instance; } WindowManager::WindowManager(QObject *parent) : QObject(parent) {} void WindowManager::registerWindow(IWindow *window) { if (window) m_windowMap[window->windowName()] = window; } IWindow *WindowManager::getWindow(const QString &name) { return m_windowMap.value(name, nullptr); }4. 自定义复杂对象:UserInfo.h
cpp
运行
#ifndef USERINFO_H #define USERINFO_H #include <QString> #include <QMetaType> struct UserInfo { Q_GADGET public: int id; QString name; QString phone; QString toString() const { return QString("ID:%1 姓名:%2 电话:%3").arg(id).arg(name).arg(phone); } }; Q_DECLARE_METATYPE(UserInfo) #endif5. 全局信号中心:SignalCenter.h + .cpp
SignalCenter.h
cpp
运行
#ifndef SIGNALCENTER_H #define SIGNALCENTER_H #include <QObject> #include "UserInfo.h" class SignalCenter : public QObject { Q_OBJECT public: static SignalCenter* instance(); signals: void sendTextToWindow1(const QString& text); void sendTextToWindow2(const QString& text); void sendUserInfoToAll(const UserInfo& user); private: explicit SignalCenter(QObject *parent = nullptr); static SignalCenter* m_inst; }; #endifSignalCenter.cpp
cpp
运行
#include "SignalCenter.h" SignalCenter* SignalCenter::m_inst = nullptr; SignalCenter* SignalCenter::instance() { if (!m_inst) m_inst = new SignalCenter; return m_inst; } SignalCenter::SignalCenter(QObject *parent) : QObject(parent) {}6. 窗口 1:Window1.h + .cpp
Window1.h
cpp
运行
#ifndef WINDOW1_H #define WINDOW1_H #include <QWidget> #include <QLineEdit> #include "IWindow.h" #include "UserInfo.h" class Window1 : public QWidget, public IWindow { Q_OBJECT public: explicit Window1(QWidget *parent = nullptr); QString windowName() override { return "Window1"; } QString getInputText(); void setText(const QString& text); private slots: void onReceiveText(const QString& text); void onReceiveUser(const UserInfo& user); private: QLineEdit* m_edit; }; #endifWindow1.cpp
cpp
运行
#include "Window1.h" #include "WindowManager.h" #include "SignalCenter.h" #include <QVBoxLayout> #include <QLabel> Window1::Window1(QWidget *parent) : QWidget(parent) { WindowManager::instance()->registerWindow(this); QVBoxLayout* lay = new QVBoxLayout(this); lay->addWidget(new QLabel("窗口 1")); m_edit = new QLineEdit("我是窗口1的内容"); lay->addWidget(m_edit); // 绑定信号 connect(SignalCenter::instance(), &SignalCenter::sendTextToWindow1, this, &Window1::onReceiveText); connect(SignalCenter::instance(), &SignalCenter::sendUserInfoToAll, this, &Window1::onReceiveUser); } QString Window1::getInputText() { return m_edit->text(); } void Window1::setText(const QString &text) { m_edit->setText(text); } void Window1::onReceiveText(const QString &text) { m_edit->setText("信号通知:" + text); } void Window1::onReceiveUser(const UserInfo &user) { m_edit->setText("收到用户:" + user.toString()); }7. 窗口 2:Window2.h + .cpp
Window2.h
cpp
运行
#ifndef WINDOW2_H #define WINDOW2_H #include <QWidget> #include "IWindow.h" class Window2 : public QWidget, public IWindow { Q_OBJECT public: explicit Window2(QWidget *parent = nullptr); QString windowName() override { return "Window2"; } private slots: void getFromWindow1(); void setToWindow1(); void sendSignalToWin1(); void sendComplexDataToAll(); }; #endifWindow2.cpp
cpp
运行
#include "Window2.h" #include "Window1.h" #include "WindowManager.h" #include "SignalCenter.h" #include <QVBoxLayout> #include <QPushButton> #include <QMessageBox> Window2::Window2(QWidget *parent) : QWidget(parent) { WindowManager::instance()->registerWindow(this); QVBoxLayout* lay = new QVBoxLayout(this); QPushButton* btnGet = new QPushButton("获取窗口1的内容"); QPushButton* btnSet = new QPushButton("修改窗口1的内容"); QPushButton* btnSig = new QPushButton("发信号给窗口1"); QPushButton* btnUser = new QPushButton("发送复杂用户对象"); lay->addWidget(btnGet); lay->addWidget(btnSet); lay->addWidget(btnSig); lay->addWidget(btnUser); connect(btnGet, &QPushButton::clicked, this, &Window2::getFromWindow1); connect(btnSet, &QPushButton::clicked, this, &Window2::setToWindow1); connect(btnSig, &QPushButton::clicked, this, &Window2::sendSignalToWin1); connect(btnUser, &QPushButton::clicked, this, &Window2::sendComplexDataToAll); } void Window2::getFromWindow1() { Window1* win1 = WindowManager::instance()->getWindowT<Window1>("Window1"); if (win1) { QString text = win1->getInputText(); QMessageBox::information(this, "读取成功", "窗口1内容:\n" + text); } } void Window2::setToWindow1() { Window1* win1 = WindowManager::instance()->getWindowT<Window1>("Window1"); if (win1) { win1->setText("来自窗口2:你被修改了!"); } } void Window2::sendSignalToWin1() { SignalCenter::instance()->sendTextToWindow1("我是窗口2,通过信号槽发来的消息!"); } void Window2::sendComplexDataToAll() { UserInfo user; user.id = 1001; user.name = "企业级架构师"; user.phone = "13888888888"; SignalCenter::instance()->sendUserInfoToAll(user); }8. 主窗口:MainWindow.h + .cpp
MainWindow.h
cpp
运行
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QStackedWidget> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); private slots: void showWin1(); void showWin2(); void accessBoth(); private: QStackedWidget* m_stack; }; #endifMainWindow.cpp
cpp
运行
#include "MainWindow.h" #include "Window1.h" #include "Window2.h" #include "WindowManager.h" #include <QPushButton> #include <QHBoxLayout> #include <QVBoxLayout> #include <QMessageBox> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { resize(500, 400); QPushButton* btn1 = new QPushButton("窗口1"); QPushButton* btn2 = new QPushButton("窗口2"); QPushButton* btnAll = new QPushButton("主窗口访问所有窗口"); QHBoxLayout* btnLay = new QHBoxLayout; btnLay->addWidget(btn1); btnLay->addWidget(btn2); btnLay->addWidget(btnAll); m_stack = new QStackedWidget; m_stack->addWidget(new Window1); m_stack->addWidget(new Window2); QVBoxLayout* mainLay = new QVBoxLayout; mainLay->addLayout(btnLay); mainLay->addWidget(m_stack); QWidget* w = new QWidget; w->setLayout(mainLay); setCentralWidget(w); connect(btn1, &QPushButton::clicked, this, &MainWindow::showWin1); connect(btn2, &QPushButton::clicked, this, &MainWindow::showWin2); connect(btnAll, &QPushButton::clicked, this, &MainWindow::accessBoth); } void MainWindow::showWin1() { m_stack->setCurrentIndex(0); } void MainWindow::showWin2() { m_stack->setCurrentIndex(1); } void MainWindow::accessBoth() { Window1* win1 = WindowManager::instance()->getWindowT<Window1>("Window1"); QString msg = "主窗口读取:\n"; if (win1) msg += "窗口1:" + win1->getInputText() + "\n"; QMessageBox::information(this, "全局访问", msg); }9. 入口:main.cpp
cpp
运行
#include <QApplication> #include "MainWindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }运行方法(10 秒搞定)
- 打开 Qt Creator
- 新建 → 其他项目 → 空 qmake 项目
- 把上面所有文件一一对应创建并复制
- 构建 → 运行
运行后你能体验到
- 窗口自由切换
- 直接读写另一个窗口内容
- 信号槽跨窗口通信
- 传递自定义复杂对象(用户信息)
- 主窗口全局访问所有窗口
这就是企业级可直接商用的完整 Qt 多窗口架构!
这套 Qt 架构用了哪些设计模式?(极简清晰版)
我给你用最通俗、最专业、面试 / 写文档都能用的方式总结:
1.单例模式(Singleton)—— 核心灵魂
用在哪里:
WindowManager窗口管理器SignalCenter信号中心
作用:
- 全局只有一个实例
- 任何窗口、任何地方,都能直接访问
- 不会重复创建、不会混乱
代码体现:
cpp
运行
WindowManager::instance(); SignalCenter::instance();2.接口抽象模式(Interface / 抽象类)
用在哪里:
IWindow纯虚接口
作用:
- 统一所有窗口的规范
- 让管理器能统一管理任意窗口
- 高内聚、低耦合
3.注册模式(Registration Pattern)
用在哪里:
- 窗口构造时自动调用
registerWindow(this)
作用:
- 窗口自己注册自己
- 管理器自动收录
- 不用手动维护窗口列表
- 新增窗口 = 0 成本
4.模板方法模式 + 安全转换模式
用在哪里:
cpp
运行
template <typename T> T* getWindowT<T>("名字");作用:
- 一行代码获取具体窗口类型
- 自动类型安全检查
- 企业级健壮写法
5.观察者模式(Observer)—— Qt 信号槽本质
用在哪里:
SignalCenter信号中心- 所有窗口信号槽通信
作用:
- 发送方 ↔ 接收方完全解耦
- 异步通知
- 支持多窗口同时接收
6.中介者模式(Mediator)—— 架构核心思想
用在哪里:
WindowManagerSignalCenter
作用:
- 窗口之间不直接互相引用
- 全部通过「中介」通信
- 结构干净、不纠缠、不循环依赖
最终总结(写进简历 / 设计文档最标准版)
本架构采用:单例模式 + 接口抽象 + 注册模式 + 中介者模式 + 观察者模式实现了高内聚、低耦合、可扩展、可维护、可直接商用的企业级 Qt 多窗口架构。
