본문 바로가기

Programming/QT&QML

[QT, QML] MVC 패턴으로 구현

728x90
반응형
# QT Version : 5.12 
# QT Creatpr Version : 4.11
# Project name : mvc_design

My_Github_Link

 

jungmonster/qt_study_project

Qt projects for my study. Contribute to jungmonster/qt_study_project development by creating an account on GitHub.

github.com

QML Context

 

QQmlContext Class | Qt QML 5.14.2

QQmlContext Class The QQmlContext class defines a context within a QML engine. More... Header: #include qmake: QT += qml Inherits: QObject Public Types Public Functions Detailed Description Contexts allow data to be exposed to the QML components instantiat

doc.qt.io

 

Signal Slot을 이용해서 간단히 MVC 패턴으로 동작하는 앱을 하나 생성한다.
버튼을 누르면 버튼 누른 횟수를 보여주는 앱으로 만들었다.

사실 이렇게 만드는게 MVC 패턴모단 MVVM 패턴에 더 가까운거 같다.

편하게 각 인스턴스에 접근하기 위해서 생성하는 클래스를 싱글톤 패턴을 적용해서 만들었다.

Singleton template
Singleton.h

#include <iostream>

template <class T>
class Singleton
{
public:
    static T* Instance() {
        if(!m_pInstance) {
            m_bInitialized = true;
            m_pInstance = new T;
        }
        assert(m_pInstance !=NULL);
        return m_pInstance;
    }

    static void destroyInstance() {
        if (m_pInstance) {
            delete m_pInstance;
            m_pInstance = NULL;
        }
    }

    static bool m_bInitialized;

protected:
    Singleton() {

    }
private:
    static T* m_pInstance;
    Singleton(Singleton const&);
    Singleton& operator=(Singleton const&);
};

template <class T> T* Singleton<T>::m_pInstance = NULL;
template <class T> bool Singleton<T>::m_bInitialized = false;

먼저 Model에 해당하는 Model Class를 생성한다.

integer 값인 btnCount를 READ, WRITE, NOTIFY 타입으로 만든다.

Q_PROPERTY로 해당 프로퍼티를 등록하면 각 타입에 맞는 함수를 간단히 콜 가능하다.

Q_PROPERTY를 사용하기 위해서는 QObject를 상속 받아야 한다.

#include <QObject>
#include <Singleton.h>

class Model : public QObject, public Singleton<Model>
{
Q_OBJECT
public:
    Q_PROPERTY(int btnCount READ btnCount WRITE set_btnCount NOTIFY changed_btnCount)

    int btnCount();
public slots:
    void set_btnCount(int data);

signals:
    void changed_btnCount(int data);

private:
    int m_btnCount;
public:
    Model();
};

int Model::btnCount()
{
    return this->m_btnCount;
}

void Model::set_btnCount(int data)
{
    this->m_btnCount = data;
    emit changed_btnCount(this->m_btnCount);
}

Model::Model()
{
    this->m_btnCount = 0;
}

다음은 버튼 이벤트를 처리하기 위한 Control 클래스를 생성한다.
버튼 클릭 시 click_btn() 함수가 콜 되고 Model의 값을 변경한다.
Model은 싱글톤으로 만들었기 때문에 같은 인스턴스의 값이 변경된다.

#include <QObject>
#include <model.h>
#include <Singleton.h>
#include <QDebug>

class Control : public QObject, public Singleton<Control>
{
Q_OBJECT

public slots:
    void click_btn();


public:
    Control();
};

void Control::click_btn()
{
    int num = Model::Instance()->btnCount();
    Model::Instance()->set_btnCount(num+1);
    qDebug() << " button";
}

Control::Control()
{

}

다음 main 함수에서 setContextProperty()를 사용해서 각 인스턴스를 등록 한다.
등록하면 qml에서 해당 Property로 접근이 가능하다.

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include <model.h>
#include <control.h>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    engine.rootContext()->setContextProperty("Model", Model::Instance());
    engine.rootContext()->setContextProperty("Controls", Control::Instance());

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

간단히 Text에선 Model 값을 출력하는데 btnCount 값이 바뀌면 자동으로 업데이트 된다.
그리고 Button Click 시 click_btn() 함수를 콜 한다.
qml

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Text{
        x : 100
        y : 100
        font.pixelSize: 30
        text : "" + Model.btnCount
    }

    Button {
        x : 100
        y : 200
        text: "button"
        onClicked: {
            Controls.click_btn()
        }
    }
}
반응형