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

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

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

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

Qt5.9/C++架构实例(一个简单的MCV架构应用实例)_第1张图片

a1.UI界面点击按钮,发射一个控制器启动信号;

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

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

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

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

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

 

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

Qt5.9/C++架构实例(一个简单的MCV架构应用实例)_第2张图片

 

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 
#include 
#include 
#include 
#include 

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 
#include 

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(buttonGroup->checkedButton());
    QString objectNameCheckedBtn = checkedButton->objectName();
    if(objectNameCheckedBtn.compare(QStringLiteral("firstPageBtn"))==0)
    {
        qDebug()<setCurrentIndex(0);
    }
    else if(objectNameCheckedBtn.compare(QStringLiteral("secondPageBtn"))==0)
    {
        qDebug()<setCurrentIndex(1);
    }
}

 

firstpagecontroller.h

#ifndef FIRSTPAGECONTROLLER_H
#define FIRSTPAGECONTROLLER_H

#include 
#include 
#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 

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()<

 

secondpagecontroller.h

#ifndef SECONDPAGECONTROLLER_H
#define SECONDPAGECONTROLLER_H

#include 

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 

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 

QFirstPageFunction::QFirstPageFunction(QObject *parent) : QObject(parent)
{    
}

void QFirstPageFunction::count_slot()
{
    int a = 2;
    int b = 3;
    QFirstPageController::GetInstance()->finishedCount_signal();
    qDebug()<

 

secondpagefunction.h

#ifndef SECONDPAGEFUNCTION_H
#define SECONDPAGEFUNCTION_H

#include 

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 

QSecondPageFunction::QSecondPageFunction(QObject *parent) : QObject(parent)
{
}

void QSecondPageFunction::count_slot()
{
    int a = 2;
    int b = 3;
    qDebug()<

 

firstpagewidget.h

#ifndef FIRSTPAGEWIDGET_H
#define FIRSTPAGEWIDGET_H

#include 
#include 

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 
#include 
#include 

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()<

 

secondpagewidget.h

#ifndef SECONDPAGEWIDGET_H
#define SECONDPAGEWIDGET_H

#include 
#include 

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 

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 
#include 

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程序构建运行后,效果如下图所示

Qt5.9/C++架构实例(一个简单的MCV架构应用实例)_第3张图片

 

Qt5.9/C++架构实例(一个简单的MCV架构应用实例)_第4张图片

 

Qt5.9/C++架构实例(一个简单的MCV架构应用实例)_第5张图片

 

源代码下载地址如下:

https://download.csdn.net/download/naibozhuan3744/10651865

 

 

参考内容:

https://blog.csdn.net/naibozhuan3744/article/details/82383683(参考:Qt5.9/C++理论)

你可能感兴趣的:(嵌入式积累,Qt工程应用)