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

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.h

2. 接口:IWindow.h

cpp

运行

#ifndef IWINDOW_H #define IWINDOW_H #include <QString> class IWindow { public: virtual ~IWindow() = default; virtual QString windowName() = 0; }; #endif

3. 窗口管理器: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; }; #endif

WindowManager.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) #endif

5. 全局信号中心: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; }; #endif

SignalCenter.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; }; #endif

Window1.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(); }; #endif

Window2.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; }; #endif

MainWindow.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 秒搞定)

  1. 打开 Qt Creator
  2. 新建 → 其他项目 → 空 qmake 项目
  3. 把上面所有文件一一对应创建并复制
  4. 构建 → 运行

运行后你能体验到

  • 窗口自由切换
  • 直接读写另一个窗口内容
  • 信号槽跨窗口通信
  • 传递自定义复杂对象(用户信息)
  • 主窗口全局访问所有窗口

这就是企业级可直接商用的完整 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)—— 架构核心思想

用在哪里:

  • WindowManager
  • SignalCenter

作用:

  • 窗口之间不直接互相引用
  • 全部通过「中介」通信
  • 结构干净、不纠缠、不循环依赖

最终总结(写进简历 / 设计文档最标准版)

本架构采用:单例模式 + 接口抽象 + 注册模式 + 中介者模式 + 观察者模式实现了高内聚、低耦合、可扩展、可维护、可直接商用的企业级 Qt 多窗口架构。

http://www.jsqmd.com/news/947929/

相关文章:

  • Vibe-Trading:赋予交易助手全面能力,多特性助力金融研究与交易!
  • 收藏必备!小白程序员快速掌握大模型:AI Agent 代码产出与架构质量平衡秘籍
  • 2026年6月热门的储能电站服务商推荐,大型光伏储能电站/农村光伏电站/新能源光伏电站,储能电站服务商推荐 - 品牌推荐师
  • 目前靠谱的TPO融合瓦厂家 - GrowthUME
  • 2026 年东北玉米种子哪家强?四家企业格局深度解析 - 勤劳的黄色小蜜蜂
  • 杭州源睿汽车服务:建德靠谱的中巴车租赁公司怎么联系 - LYL仔仔
  • 2026年笔记本维修全攻略,换屏幕换电池清灰重装系统一站解决 - 资讯焦点
  • 如何快速部署YI-1.5-9B:5步完成中文大语言模型本地安装
  • 轻量化大模型工程实践:低延迟高保真LLM端侧部署指南
  • 多维度可视化分析,智能数据驱动全周期教学质量评估 - 玖叁鹿
  • Granite Guardian 3.0-2b-GGUF性能评测:横扫12项权威基准,F1分数高达0.98
  • GPT2_PMC-openmind性能优化指南:提升医学问答准确率的3个技巧
  • 实战应用:基于快马平台与openhuman开发虚拟试衣演示系统
  • 破解工业废水处理定制难题:GCE全链路定制化达标方法论如何实现稳定达标? - 资讯快报
  • 鸿蒙Flutter实战:IndexedStack保持Tab页面状态
  • Vicuna-7B配置文件详解:优化模型参数提升对话质量
  • VisRAG-Ret性能优化秘籍:提升视觉检索效率的10个技巧
  • 江苏省采购证书怎么选择怎么考?2026年CPPM注册职业采购经理报考全攻略(官方授权版) - 众智商学院课程中心
  • Python爬虫实战:构建你的“国家标准”本地索引库!
  • 第222期方班学术研讨厅(复盘课)成功举办
  • 2026 安庆全域工装甄选指南|迎江 / 大观 / 宜秀 / 桐城 / 怀宁 / 宿松全区域商铺、办公室、商场装修 3 家正规合规企业排行 + 本地装修避坑全攻略 - 本地便民网
  • AceGPT-v1.5-13B模型压缩与优化:降低推理成本的10个技巧
  • WinUtil:一键解决Windows系统三大痛点的终极免费工具指南
  • Rose/flan-t5-xxl-SFT与OpenMind框架:华为NPU上的高效AI推理方案
  • Vue3 + Element Plus 实战:用Composition API重构el-tabs动态加载表格(对比Vue2选项式API)
  • 【Git】-- 标签管理
  • 嵌入式培训避坑指南:只有具备真实量产研发能力的企业才能教会你真技术 - 资讯焦点
  • Java 过时了吗?深度分析职业前景、技术生态与学习路线
  • 2026 泾县黄金回收靠谱商家推荐|铂金白银 K 金金条首饰回收价格与门店指南 - 同城好物推荐官
  • BetterJoy终极指南:如何让Switch控制器在PC上完美工作