个人技术分享

一、采用QT对方法提供的宏进行结构MVVM的构建

1.打开QT ,并创建QT-QUICK 工程,建议QT5.15及以上

2.准备 类 MyObject  其实这个类就可以作为VM使用

myobject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>

class MyObject : public QObject
{
    Q_OBJECT
public:
    explicit MyObject(QObject *parent = nullptr);

    Q_INVOKABLE QString func(QString str);//需要调用的函数

    //单例
    static MyObject* getInstance(){
        static MyObject* myobj = new MyObject() ;
        return myobj;
    };


    int iValue() const;
    void setIValue(int newIValue);

    const QString &sString() const;
    void setSString(const QString &newSString);

signals:
    void iValueChanged();

    void sStringChanged();

private:
    int m_iValue;		//针对变量 alt+enter 会自动创建一系列相关方法和宏定义
    QString m_sString="init";

//signals:


    //这里的通知动作iValueChanged sStringChanged非常重要,是属性变化后 通知前端做同步的核心
    Q_PROPERTY(int iValue READ iValue WRITE setIValue NOTIFY iValueChanged)
    Q_PROPERTY(QString sString READ sString WRITE setSString NOTIFY sStringChanged)
};

#endif // MYOBJECT_H

myobject.cpp

#include "myobject.h"
#include <QDebug>

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


}


//需要调用的函数 
//这里有个重点  必须采用setSString方法来设置sString的值,这样才能启动通知,等号赋值不会通知前端
QString MyObject::func(QString str)
{
    setSString(sString()+ str + '#' ) ;
    // m_sString = str+"@";
    qDebug()<< __FUNCTION__ <<" === "<<str;
    return sString();
}

int MyObject::iValue() const
{
    return m_iValue;
}

void MyObject::setIValue(int newIValue)
{
    if (m_iValue == newIValue)
        return;
    m_iValue = newIValue;
    emit iValueChanged();
}

const QString &MyObject::sString() const
{
    return m_sString;
}

void MyObject::setSString(const QString &newSString)
{
    if (m_sString == newSString)
        return;
    m_sString = newSString;
    emit sStringChanged();
}

3 main.cpp中连接创建的类

main.cpp  如果版本较新则采用注册单例qmlRegisterSingletonInstance方式进行 

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "myobject.h"

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
 
    //关键//
    qmlRegisterSingletonInstance( "MyObj",1,0,"MyObjectIns",MyObject::getInstance());

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

4 qml部分  作为view

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.5
import MyObj 1.0

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

    onWidthChanged: { console.log(width) }

    //ref动态绑定 由于iValue定义了通知动作;
    //一个改变 会通知另一个改变  建议用此承接前端属性
    property string sstring: MyObjectIns.sString

    Text {
        id: txt
        text: sstring
    }

    Button {
        objectName: "myButton"
        width:100
        height:100
        y:100
        onClicked: {
            MyObjectIns.func("ee")
            console.log ( MyObjectIns.sString)
            console.log (txt.text)
            console.log (sstring)
        }
    }
}

其他后续问题

可见目前只是通过按钮修改后台数据,并在view绑定了前端的属性进行同步变化;

那么如果我需要改变通知的是个表格呢?

我们可能需要采用更加复杂的数据结构和复杂的更新机制;