qml 组件化编程 MVC编程一
MVC编程,通俗的说就是实现数据、视图与业务的分离,采用分而治之的模式。也许很多人知道MVC是怎么回事,但是用起来却有点无从下手,那么我们先从小Deml说起。上代码
1、model与view分离,但是仍在qml中实现所有
import QtQuick 2.3 Rectange{ width: 450 height: 640; GridView{ id: showView anchors.fill: parent cellWidth: 50 cellHeight: 50 model: dataModel delegate: delegateComp } Component{ id: delegateComp Rectangle{ width: viewWidth height: viewHeight color: itemColor } } ListModel{ id: dateModel ListElement{viewWidth: 50; viewHeight: 50; itemColor: "red"} ListElement{viewWidth: 20; viewHeight: 50; itemColor: "yellow"} ListElement{viewWidth: 100; viewHeight: 100; itemColor: "blue"} } }
效果图如下:

这里我们实现了一个最简单的MVC组件。但是从上图中效果有点费解,为什么设置了大小,却没起作用,甚至各个组件之间会有空白。这是因为GridView中cellWIdth决定的。如果组件的大小被cell的大小包含,那么cell比组件多出来的部分会用空白填充;反过来,如果组件的大小比cell大,那么就会被裁剪成cell大小,如蓝色框一般
(1)现在我们在升级一部分功能,将小框组件化
//Rect.qml import QtQuick 2.3 Rectangle{ } //main.qml
import QtQuick 2.3 Rectange{ width: 450 height: 640; GridView{ id: showView anchors.fill: parent cellWidth: 50 cellHeight: 50 model: dataModel delegate: delegateComp } Component{ id: delegateComp Rect{ width: viewWidth height: viewHeight color: itemColor } } ListModel{ id: dateModel ListElement{viewWidth: 50; viewHeight: 50; itemColor: "red"} ListElement{viewWidth: 20; viewHeight: 50; itemColor: "yellow"} ListElement{viewWidth: 100; viewHeight: 100; itemColor: "blue"} } }
我们通过把委托中的组件单独封装成一个独立的组件,这样不仅在这里可以使用,在其他地方也可以创建
(2)把Model从qml中剥离出来
既然是组件化编程,那么数据是动态的,视图也是根据数据动态创建。而数据一般是由业务侧产生,业务侧我们由C++实现,这里先把业务动作隐藏,直接产生测试数据。
//ModelClass class Apple{ public: Apple(); Q_INVOKABLE QVariant getProperty(); private: int m_nWidth; int m_nHeight; QString m_strColor; } //main.cpp int main() { qmlRegisterType<Apple>("Model.Fruit", 1, 0, "Apple"); } //main.qml Rectanle{ //MVC部分省略... Apple{ id: appleObj } Component.onCompleted:{ dateModel.append(appleObj.getProperty()) } }
在上面中,我们定义一个model类,用于产生数据,在适当的时机(比如创建组件完成后)把数据绑定到ListModel上。
同样,我们可以通过信号,当model类需要更新数据时,可以通过信号实现通知
(3)多层嵌套组件的数据透传
上面只是一层的MVC,如果有多层的MVC,我们该如何把数据传到最底层呢?这就是本文章的最终说明,有一下几种方法
1、C++侧根据数据,通过创建Component的方式加载qml,然后调用invokeMethod的方式将数据传过去
2、qml采用MVC模式,C++侧实现Model,通过信号发送数据
3、model仍然在C++侧,但是qml中采用createComponent的方式创建。
对于上面的几种方式,这里有几个关键的函数说明
对于第一种,
QQmlEngine *pEngine = view.engine(); QQuickItem *pRootItem = view.rootObject()->findChild<QQuickItem*>("MainCanvas"); QQmlComponent comPont(pEngine, QUrl(QStringLiteral("qrc:;/test.qml"))); QQuickItem *pFirstItem = dynamic_cast<QQuickItem*>(comPont.create()); pFistItem->setParentItem(pRootItem);
QMetaObject::invokeMethod(pFirstItem, "onDraw", Q_ARG(QVariant, varFontInfo));
对于第二和第三种,见源代码

浙公网安备 33010602011771号