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 秒搞定)
- 打开 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 多窗口架构。