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 多窗口架构。

相关推荐
韦胖漫谈IT1 小时前
面向对象 vs 函数式背后的思维差异
开发语言
Xin_ye100861 小时前
C# 零基础到精通教程 - WPF 深度专题:3D 图形与视觉增强
开发语言·c#·wpf
zhangfeng11332 小时前
台大李宏毅老师讲解memba和类似linear atttenion 模型,笔记
开发语言·人工智能·笔记
Chris _data3 小时前
并发单词频率统计器 - 从零到完整实现(C# 实战)
开发语言·c#
idolao3 小时前
Oligo 7.60 安装教程:引物设计+Java 环境配置
java·开发语言
不知名的老吴3 小时前
Lambda表达式与新的Streams API相结合
开发语言·python
石山代码10 小时前
ArrayList / HashMap / ConcurrentHashMap
java·开发语言
程序大视界10 小时前
【Python系列课程】Python正则表达式(下):环视、命名分组与日志实战
开发语言·python·正则表达式
jingshaoqi_ccc11 小时前
windows 10系统下QT的安装及在Visual studio中的扩展安装
windows·qt·visual studio