Qt5.9/C++架构实例(一个简单的MCV架构应用实例)
Published on 2022-06-01 09:37 in 分类: Qt with 萧海~
分类: Qt

Qt5.9/C++架构实例(一个简单的MCV架构应用实例)

    本文主要在Qt5.9/C++桌面应用项目开发中,总结一个常用的程序架构(或框架),整个工程主要分为三大模块,分别为视图层、控制层、模型层。其中,视图层完全负责界面类的编写和展示;控制层完全负责处理逻辑,将UI界面和模型层的功能有机结合起来;模型层主要负责实现业务逻辑功能。

    实现一个业务逻辑功能时,控制层是主要层;有三个主要的信号,分别是启动信号、完成信号、显示结果界面信号,具体的可以参考博主这篇文章:https://blog.csdn.net/naibozhuan3744/article/details/82383683。其中,控制层所有类都是采用单例模型,具有唯一的实例、提供一个全局接口的优点。

    实现一个按钮功能步骤如下:(改进思路:控制层controller作为信号产生中转信号,建立一个控制层文件就行)

    在这里插入图片描述
    a1.UI界面点击按钮,发射一个控制器启动信号;

    a2.控制层开启一条支线层,执行模型层功能函数;

    a3.模型层功能函数执行完后,发射一个完成控制层信号,表明完成了该业务逻辑功能;

    a4.控制层停止该支线层,并且发射一个显示完成业务逻辑UI界面信号;

    a5.UI界面接收业务逻辑完成信号,显示完成功能界面。

    具体的编程实例如下所述。

    1.1新建一个widget工程,不要勾选ui界面。然后分别在添加视图层类(QFirsrPageWidget、QSecondPageWidget)、控制器层类(QFirsrPageController、QSecondPageController)、模型层类(QFirsrPageFunction、QSecondPageFunction),如下图所示:

    在这里插入图片描述
    1.2分别在widget.h、widget.cpp;firstpagecontroller.h、firstpagecontroller.cpp;secondpagecontroller.h、secondpagecontroller.cpp;firstpagefunction.h、firstpagefunction.cpp;secondpagefunction.h、secondpagefunction.cpp;firstpagewidget.h、firstpagewidget.cpp;secondpagewidget.h、secondpagewidget.cpp;类中添加如下代码:

    widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    #include <QWidget>
    #include <QVBoxLayout>
    #include <QHBoxLayout>
    #include <QStackedLayout>
    #include <QButtonGroup>
    class Widget : public QWidget
    {
    Q_OBJECT
    public:
    Widget(QWidget *parent = 0);
    ~Widget();
    private:
    void setupUI();
    void initMenu();
    void initStackWidget();
    QVBoxLayout *mainLayout;
    QButtonGroup *buttonGroup;
    QStackedLayout *stackLayout;
    // QWidget *firstPageWidget;
    // QWidget *secondPageWidget;
    private slots:
    void buttonGroupSlot(int);
    };
    #endif // WIDGET_H

    widget.cpp

    #include "widget.h"
    #include "view/firstpagewidget.h"
    #include "view/secondpagewidget.h"
    #include <QPushButton>
    #include <QDebug>
    Widget::Widget(QWidget *parent)
    : QWidget(parent)
    {
    setupUI();
    }
    Widget::~Widget()
    {
    }
    void Widget::setupUI()
    {
    mainLayout = new QVBoxLayout;
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);
    QWidget *mainWidget = new QWidget(this); /*启动QWidget页面需要制定父对象this指针,不然会出现闪屏bug*/
    mainWidget->setLayout(mainLayout);
    mainWidget->setObjectName("mainWidget");
    mainWidget->setStyleSheet("#mainWidget{border-image:url(:/resource/main_bg.jpg)}"); /*设置主界面背景图片*/
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->setSpacing(0);
    layout->addWidget(mainWidget);
    this->setLayout(layout);
    /*初始化顶层菜单栏、底层功能区*/
    initMenu();
    initStackWidget();
    }
    void Widget::initMenu()
    {
    const QSize btnSize(120,90);
    /*菜单按钮初始化*/
    QPushButton *firstPageBtn = new QPushButton(tr("\n\n\n\n\n第一页"));
    firstPageBtn->setObjectName("firstPageBtn");
    firstPageBtn->setCheckable(true);
    firstPageBtn->setChecked(true);
    firstPageBtn->setFixedSize(btnSize);
    firstPageBtn->setStyleSheet("QPushButton{border-image: url(:/resource/icon_page1.png) 0 0 0 0;background-repeat: no-repeat;background-position:center;border:none;color:rgb(255, 255, 255);}"
    "QPushButton:hover{border-image: url(:/resource/icon_page1.png) 5 0 0 0;background-repeat: no-repeat;background-position:center;border:none;color:rgb(255, 255, 255);}"
    "QPushButton:checked{border-image: url(:/resource/icon_page1.png) 4 0 0 0;background-repeat: no-repeat;background-position:center;border:none;color:rgb(255, 255, 255);}");
    QPushButton *secondPageBtn = new QPushButton(tr("\n\n\n\n\n第二页"));
    secondPageBtn->setObjectName("secondPageBtn");
    secondPageBtn->setCheckable(true);
    secondPageBtn->setFixedSize(btnSize);
    secondPageBtn->setStyleSheet("QPushButton{border-image: url(:/resource/icon_page2.png) 0 0 0 0;background-repeat: no-repeat;background-position:center;border:none;color:rgb(255, 255, 255);}"
    "QPushButton:hover{border-image: url(:/resource/icon_page2.png) 5 0 0 0;background-repeat: no-repeat;background-position:center;border:none;color:rgb(255, 255, 255);}"
    "QPushButton:checked{border-image: url(:/resource/icon_page2.png) 4 0 0 0;background-repeat: no-repeat;background-position:center;border:none;color:rgb(255, 255, 255);}");
    /*单选菜单效果*/
    buttonGroup = new QButtonGroup();
    buttonGroup->setObjectName("buttonGroup");
    buttonGroup->addButton(firstPageBtn);
    buttonGroup->addButton(secondPageBtn);
    buttonGroup->setExclusive(true);
    connect(buttonGroup,SIGNAL(buttonClicked(int)),this,SLOT(buttonGroupSlot(int)));
    /*容器包含*/
    QHBoxLayout *menuLayout = new QHBoxLayout();
    menuLayout->setMargin(0);
    menuLayout->setSpacing(0);
    menuLayout->addWidget(firstPageBtn);
    menuLayout->addWidget(secondPageBtn);
    menuLayout->addStretch();
    mainLayout->addLayout(menuLayout);
    }
    void Widget::initStackWidget()
    {
    /*启动菜单栏界面*/
    QFirstPageWidget *firstPageWidget = new QFirstPageWidget(this); /*启动QWidget页面需要制定父对象this指针,不然会出现闪屏bug*/
    QSecondPageWidget *secondPageWidget = new QSecondPageWidget(this);
    stackLayout = new QStackedLayout;
    stackLayout->addWidget(firstPageWidget);
    stackLayout->addWidget(secondPageWidget);
    stackLayout->setCurrentIndex(0);
    mainLayout->addLayout(stackLayout);
    }
    void Widget::buttonGroupSlot(int)
    {
    QPushButton* checkedButton = qobject_cast<QPushButton*>(buttonGroup->checkedButton());
    QString objectNameCheckedBtn = checkedButton->objectName();
    if(objectNameCheckedBtn.compare(QStringLiteral("firstPageBtn"))==0)
    {
    qDebug()<<tr("单击了第一页菜单按钮");
    stackLayout->setCurrentIndex(0);
    }
    else if(objectNameCheckedBtn.compare(QStringLiteral("secondPageBtn"))==0)
    {
    qDebug()<<tr("单击了第二页菜单按钮");
    stackLayout->setCurrentIndex(1);
    }
    }

    firstpagecontroller.h

    #ifndef FIRSTPAGECONTROLLER_H
    #define FIRSTPAGECONTROLLER_H
    #include <QObject>
    #include <QThread>
    #include "model/firstpagefunction.h"
    class QFirstPageController : public QObject
    {
    Q_OBJECT
    public:
    static QFirstPageController* GetInstance();
    signals:
    void startedCount_signal();
    void finishedCount_signal();
    void showFinishedCountUI_signal();
    private:
    static QFirstPageController *m_instance;
    QFirstPageController();
    void initController();
    QThread *threadCount;
    QFirstPageFunction *firstPageFunction;
    private slots:
    void startCountSlot();
    void quitCountThreadSlot();
    void finishedCountThreadSlot();
    };
    #endif // FIRSTPAGECONTROLLER_H

    firstpagecontroller.cpp

    #include "firstpagecontroller.h"
    #include <QDebug>
    QFirstPageController *QFirstPageController::m_instance = new QFirstPageController();
    QFirstPageController *QFirstPageController::GetInstance()
    {
    return m_instance;
    }
    QFirstPageController::QFirstPageController()
    {
    /*初始化*/
    initController();
    }
    void QFirstPageController::initController()
    {
    /*绑定信号与槽函数*/
    connect(this,SIGNAL(startedCount_signal()),this,SLOT(startCountSlot()));
    }
    void QFirstPageController::startCountSlot()
    {
    /*启动一对一镜像线程*/
    threadCount = new QThread;
    firstPageFunction = new QFirstPageFunction();
    firstPageFunction->moveToThread(threadCount);
    connect(threadCount,SIGNAL(finished()),threadCount,SLOT(deleteLater()));
    connect(threadCount,SIGNAL(started()),firstPageFunction,SLOT(count_slot())); /*多线程槽函数*/
    connect(this,SIGNAL(finishedCount_signal()),this,SLOT(quitCountThreadSlot()));
    connect(threadCount,SIGNAL(finished()),this,SLOT(finishedCountThreadSlot()));
    threadCount->start();
    }
    void QFirstPageController::quitCountThreadSlot()
    {
    threadCount->quit();
    threadCount->wait();
    }
    void QFirstPageController::finishedCountThreadSlot()
    {
    qDebug()<<tr("完成计算逻辑功能!!!");
    emit showFinishedCountUI_signal();
    }

    secondpagecontroller.h

    #ifndef SECONDPAGECONTROLLER_H
    #define SECONDPAGECONTROLLER_H
    #include <QObject>
    class QSecondPageController : public QObject
    {
    Q_OBJECT
    public:
    static QSecondPageController* GetInstance();
    signals:
    void count_signal();
    private:
    static QSecondPageController *m_instance;
    QSecondPageController();
    private slots:
    };
    #endif // SECONDPAGECONTROLLER_H

    secondpagecontroller.cpp

    #include "secondpagecontroller.h"
    QSecondPageController *QSecondPageController::m_instance = new QSecondPageController();
    QSecondPageController *QSecondPageController::GetInstance()
    {
    return m_instance;
    }
    QSecondPageController::QSecondPageController()
    {
    }

    firstpagefunction.h

    #ifndef FIRSTPAGEFUNCTION_H
    #define FIRSTPAGEFUNCTION_H
    #include <QObject>
    class QFirstPageFunction : public QObject
    {
    Q_OBJECT
    public:
    explicit QFirstPageFunction(QObject *parent = nullptr);
    signals:
    public slots:
    void count_slot();
    };
    #endif // FIRSTPAGEFUNCTION_H

    firstpagefunction.cpp

    #include "firstpagefunction.h"
    #include "controller/firstpagecontroller.h"
    #include <QDebug>
    QFirstPageFunction::QFirstPageFunction(QObject *parent) : QObject(parent)
    {
    }
    void QFirstPageFunction::count_slot()
    {
    int a = 2;
    int b = 3;
    QFirstPageController::GetInstance()->finishedCount_signal();
    qDebug()<<tr("页面1的逻辑功能计算结果为==%1").arg(a+b);
    }

    secondpagefunction.h

    #ifndef SECONDPAGEFUNCTION_H
    #define SECONDPAGEFUNCTION_H
    #include <QObject>
    class QSecondPageFunction : public QObject
    {
    Q_OBJECT
    public:
    explicit QSecondPageFunction(QObject *parent = nullptr);
    signals:
    public slots:
    void count_slot();
    };
    #endif // SECONDPAGEFUNCTION_H

    secondpagefunction.cpp

    #include "secondpagefunction.h"
    #include <QDebug>
    QSecondPageFunction::QSecondPageFunction(QObject *parent) : QObject(parent)
    {
    }
    void QSecondPageFunction::count_slot()
    {
    int a = 2;
    int b = 3;
    qDebug()<<tr("页面2的逻辑功能计算结果为==%1").arg(a*b);
    }

    firstpagewidget.h

    #ifndef FIRSTPAGEWIDGET_H
    #define FIRSTPAGEWIDGET_H
    #include <QWidget>
    #include <QVBoxLayout>
    class QFirstPageWidget : public QWidget
    {
    Q_OBJECT
    public:
    explicit QFirstPageWidget(QWidget *parent = nullptr);
    signals:
    private:
    void setupUI();
    QVBoxLayout *mainLayout;
    private slots:
    void showOneFunctionUISlot();
    void showFinishedCountResultUISlot();
    };
    #endif // FIRSTPAGEWIDGET_H

    firstpagewidget.cpp

    #include "firstpagewidget.h"
    #include "controller/firstpagecontroller.h"
    #include "controller/secondpagecontroller.h"
    #include <QPushButton>
    #include <QDebug>
    #include <QMessageBox>
    QFirstPageWidget::QFirstPageWidget(QWidget *parent) : QWidget(parent)
    {
    setupUI();
    }
    void QFirstPageWidget::setupUI()
    {
    QPushButton *firstPage = new QPushButton(tr("我是第一页的页面:点击我实现2+3计算功能(业务逻辑功能)"));
    connect(firstPage,SIGNAL(clicked(bool)),this,SLOT(showOneFunctionUISlot()));
    mainLayout = new QVBoxLayout(this);
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);
    mainLayout->addWidget(firstPage);
    mainLayout->addStretch();
    /*注意:这个绑定不能放在按钮那里,否则会出现第n次点击按钮,然后发射n次信号,执行n次槽函数*/
    connect(QFirstPageController::GetInstance(),SIGNAL(showFinishedCountUI_signal()),this,SLOT(showFinishedCountResultUISlot()));
    }
    void QFirstPageWidget::showOneFunctionUISlot()
    {
    /*摁下按钮,切换到新的界面*/
    QFirstPageController::GetInstance()->startedCount_signal();
    }
    void QFirstPageWidget::showFinishedCountResultUISlot()
    {
    qDebug()<<tr("显示计算后界面!!!");
    QMessageBox::warning(this,QStringLiteral("结果界面"),QStringLiteral("显示计算后界面!!!"),QMessageBox::Yes,QMessageBox::No);
    }

    secondpagewidget.h

    #ifndef SECONDPAGEWIDGET_H
    #define SECONDPAGEWIDGET_H
    #include <QWidget>
    #include <QVBoxLayout>
    class QSecondPageWidget : public QWidget
    {
    Q_OBJECT
    public:
    explicit QSecondPageWidget(QWidget *parent = nullptr);
    signals:
    public slots:
    private:
    void setupUI();
    QVBoxLayout *mainLayout;
    };
    #endif // SECONDPAGEWIDGET_H

    secondpagewidget.cpp

    #include "secondpagewidget.h"
    #include <QPushButton>
    QSecondPageWidget::QSecondPageWidget(QWidget *parent) : QWidget(parent)
    {
    setupUI();
    }
    void QSecondPageWidget::setupUI()
    {
    QPushButton *firstPage = new QPushButton(tr("我是第二页的页面:点击我实现2*3计算功能(业务逻辑功能)"));
    mainLayout = new QVBoxLayout(this);
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);
    mainLayout->addWidget(firstPage);
    mainLayout->addStretch();
    }

    main.cpp

    #include "widget.h"
    #include <QApplication>
    #include <QIcon>
    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Widget mainWidget;
    mainWidget.resize(960,640);
    mainWidget.setWindowTitle(QString::fromUtf8("Qt/C++架构工程demo版本V1.0.0"));
    mainWidget.setWindowIcon(QIcon(":/resource/main_ico.ico"));
    mainWidget.setStyleSheet("font: bold 12px;");
    mainWidget.show();
    return a.exec();
    }

    1.2程序构建运行后,效果如下图所示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    原文:https://blog.csdn.net/naibozhuan3744/article/details/82493728

    posted @   萧海~  阅读(467)  评论(0编辑  收藏  举报
    相关博文:
    阅读排行:
    · winform 绘制太阳,地球,月球 运作规律
    · AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
    · 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
    · 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
    · 上周热点回顾(3.3-3.9)
    点击右上角即可分享
    微信分享提示
    电磁波切换