我的 Qt 上位机项目 MVC 重构日记

# 我的 Qt 上位机项目 MVC 重构日记
日期: 2025-07-31


前言

今天我将把一个刚用 Qt Creator 17.0.0 + Qt 6.9.1 创建的 “Qt Widgets Application”——MyMonitorApp, 从 Qt Creator 默认的文件组织方式(头文件/源文件/界面文件三大 filter)改造成清晰的 MVC(Model–View–Controller)分层项目。


一、项目初始状态

  • Qt 版本:Qt 6.9.1

  • Creator 版本:17.0.0

  • 项目名称:MyMonitorApp

  • 磁盘目录结构(通过“文件系统”视图看到):

    MyMonitorApp/
    ├── MyMonitorApp.pro
    ├── headers/
    │   └── mainwindow.h
    ├── sources/
    │   ├── main.cpp
    │   └── mainwindow.cpp
    └── forms/
        └── mainwindow.ui
    
  • IDE “项目”视图(逻辑分组,不是真实目录):

    ├── 头文件
    ├── 源文件
    └── 界面文件
    

二、为什么要拆成 MVC?

  1. 职责分离

    • Model:负责管理和存储数据。
    • View:只关心 UI 展示(.ui + 界面类实现)。
    • Controller:处理业务逻辑、和下位机的串口/网络通信。
  2. 可维护性

    • 功能模块清晰,新同事可快速定位代码。
  3. 可扩展性

    • 增加新功能只要在对应层新增文件夹,不影响其他层。

三、重构步骤

1. 在磁盘上创建分层目录

cd MyMonitorApp
mkdir model view controller util
  • model/:放 QAbstractItemModel 子类
  • view/:放所有 .ui + 对应的 .h/.cpp
  • controller/:放业务逻辑与通讯类
  • util/:放串口管理、日志、配置等辅助工具

2. 移动文件

# View 层
mv headers/mainwindow.h    view/
mv sources/mainwindow.cpp  view/
mv forms/mainwindow.ui     view/

# 根目录下 main.cpp 保持不动或按需放 controller/

此时磁盘目录变为:

MyMonitorApp/
├── model/
├── view/
│   ├── mainwindow.h
│   ├── mainwindow.cpp
│   └── mainwindow.ui
├── controller/
├── util/
├── main.cpp
└── MyMonitorApp.pro

3. 修改 MyMonitorApp.pro

打开并编辑,将原来指向 headers/sources/forms/ 的条目全部替换成 MVC 目录下的路径:

 QT       += core gui widgets
 CONFIG   += c++17

- INCLUDEPATH += $$PWD/headers
+ INCLUDEPATH += $$PWD/model \
+                $$PWD/view \
+                $$PWD/controller \
+                $$PWD/util

- HEADERS    += headers/mainwindow.h
- SOURCES    += sources/main.cpp \
-                sources/mainwindow.cpp
- FORMS      += forms/mainwindow.ui

+ HEADERS += \
+     view/mainwindow.h \
+     model/DeviceDataModel.h \
+     controller/DeviceController.h

+ SOURCES += \
+     main.cpp \
+     view/mainwindow.cpp \
+     model/DeviceDataModel.cpp \
+     controller/DeviceController.cpp

+ FORMS += \
+     view/mainwindow.ui

小提醒:IDE “项目”视图里的 “头文件/源文件/界面文件” 只是 qmake filter,不影响真实目录。

4. 在 Qt Creator 中验证

  1. 打开项目:MyMonitorApp.pro
  2. 切换到 “文件系统” 视图,确认只剩下 model/view/controller/util/
  3. “构建→清理项目 → 运行 QMake → 编译”

四、代码骨架示例

1. Model

// model/DeviceDataModel.h
#pragma once
#include <QAbstractTableModel>
#include "DeviceItem.h"

class DeviceDataModel : public QAbstractTableModel {
    Q_OBJECT
public:
    explicit DeviceDataModel(QObject* parent = nullptr);
    int rowCount(...) const override;
    int columnCount(...) const override;
    QVariant data(...) const override;
    void appendData(const DeviceItem& item);
private:
    QVector<DeviceItem> m_items;
};

2. Controller

// controller/DeviceController.h
#pragma once
#include <QObject>
#include "model/DeviceDataModel.h"
#include "util/SerialPortManager.h"

class DeviceController : public QObject {
    Q_OBJECT
public:
    DeviceController(DeviceDataModel* model, QObject* parent = nullptr);
private slots:
    void onSerialDataReceived(const QByteArray& raw);
private:
    DeviceDataModel* m_model;
    SerialPortManager m_serial;
};

3. View

<!-- view/mainwindow.ui -->
<ui version="4.0">
  <class>MainWindow</class>
  <!-- … -->
</ui>
// view/mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_model = new DeviceDataModel(this);
    ui->tableView->setModel(m_model);
    m_ctrl  = new DeviceController(m_model, this);
}

五、心得与建议

  • IDE 视图 vs 文件系统

    • “项目”视图便于按文件类型快速定位;
    • “文件系统”视图才映射真实目录结构。
  • 分层不分味

    • 小项目可以不严格三层都写,按需增删;
    • 大项目建议在各层内部再做二级模块划分。
  • 版本管理

    • 重构后别忘了更新 .gitignore(移除旧目录引用)。

重构完毕后,MyMonitorApp 的目录变得干净整齐,逻辑分层清晰,后续新增功能或移植到嵌入式 Qt 时都省心不少。希望这篇日记对你也有帮助!

posted @ 2025-07-31 11:01  阿坦  阅读(41)  评论(0)    收藏  举报