零、前言
MVC在Qt中叫做MVD,Model+View+Delegate。关于Model,Qt提供了以QAbstractItemModel为父类的相关类。如图:
①、QAbstractItemModel提供给数据一个接口,它非常灵活,基本满足views的需要,无论数据用什么样的形式表现,如tables,lists,trees;
②、如果model基于list、table形式的数据结构,可从QAbstractListModel、QAbstractTableModel开始做起,因为它们提供了适当的常规功能的缺省实现;
③、QStringListModel 用于存储简单的QString列表;
④、QStandardItemModel 管理复杂的树型结构数据项,每项都可以包含任意数据;
⑤、QDirModel 提供本地文件系统中的文件与目录信息;
⑥、QSqlQueryModel、QSqlTableModel、QSqlRelationTableModel用来访问数据库;
假如这些标准Model不满足需要,可子类化QAbstractItemModel、QAbstractListModel、QAbstractTableModel等来定制。
PS:
根据这个原理,QXXXView和QXXXWidget的区别:View可以手动设置自定义Model进去,Widget只能用标准的自带Model;
在QML中Grid和GridView区别也是,带View的是可以设置Model的。
一、静态视图
1、Repeater+model:数字
import QtQuick 2.0 Column{ spacing:2 Repeater{ model:10 Rectangle{ 100 height:20 radius:3 color:"lightBlue" Text{ anchors.centerIn: parent text:index } } } }
Repeater会传递分配给delegate的index;
这里Rectangle前省略了delegate,建议都加上,免得看不懂。
2、Repeater+model:js序列
序列可以是字符串、整数或者对象,以字符串为例
import QtQuick 2.0 Column { spacing: 2 Repeater { model: ["Enterprise", "Colombia", "Challenger", "Discovery", "Endeav"] delegate: Rectangle { 100 height: 20 radius: 3 color: "lightBlue" Text { anchors.centerIn: parent text: index +": "+modelData } } } }
Repeater会传递分配给delegate的index和序列对象,这里是字符串。
3、Repeater+model:ListModel
import QtQuick 2.0 import QtQml.Models 2.15 Column{ spacing:2 Repeater{ model:ListModel{ ListElement{name:"Mercury";surfaceColor:"gray"} ListElement{name:"Venus";surfaceColor:"yellow"} ListElement{name:"Earth";surfaceColor:"blue"} ListElement{name:"Mars";surfaceColor:"orange"} ListElement{name:"Jupiter";surfaceColor:"orange"} ListElement{name:"Saturn";surfaceColor:"yellow"} ListElement{name:"Uranus";surfaceColor:"lightBlue"} ListElement{name:"Neptune";surfaceColor:"lightBlue"} } delegate:Rectangle{ 100 height:20 radius:3 color:"lightBlue" Text{ anchors.centerIn:parent text:name } Rectangle{ anchors.left:parent.left anchors.verticalCenter:parent.verticalCenter anchors.leftMargin:2 16 height:16 radius:8 border.color:"black" border.1 color:surfaceColor } } } }
Repeater会传递分配给delegate的index和ListElement对象,可访问ListElement里的所有元素,这是里name、serfaceColor。
PS:
①、Repeator的model里可以放的数据如下,
一个数字代表着生成多少个模型;
一个ListModel或QAbstractItemModel子类;
一个字符串列表;
一个对象列表。
4、ListView+ListModel
import QtQuick 2.5 Item { id: root 400 height: 300 ListView { anchors.fill: parent model: fruitModel delegate: Row { Text { text: "Fruit: " + name } Text { text: "Cost: $" + cost } } } ListModel { id: fruitModel ListElement { name: "Apple" cost: 2.45 } ListElement { name: "Orange" cost: 3.25 } ListElement { name: "Banana" cost: 1.95 } } }
二、动态视图
1、动态为GridView增删对象
import QtQuick 2.0 import QtQml.Models 2.15 Rectangle { 480; height: 300; //背景色渐变 gradient: Gradient { GradientStop { position: 0.0; color: "#dbddde"; } GradientStop { position: 1.0; color: "#5fc9f8"; } } //list模型默认9项 ListModel { id: theModel ListElement { number: 0; } ListElement { number: 1; } ListElement { number: 2; } ListElement { number: 3; } ListElement { number: 4; } ListElement { number: 5; } ListElement { number: 6; } ListElement { number: 7; } ListElement { number: 8; } ListElement { number: 9; } } //Add Item按钮 Rectangle { anchors.left: parent.left; anchors.right: parent.right; anchors.bottom: parent.bottom; anchors.margins: 20; height: 40; color: "#53d769"; border.color: Qt.lighter(color, 1.1); Text { anchors.centerIn: parent; text: "Add item!"; } //点击时新增项 实现model的动态新增 MouseArea { anchors.fill: parent; onClicked: { theModel.append({"number": ++parent.count}); } } property int count: 9;// } GridView { anchors.fill: parent; anchors.margins: 20; anchors.bottomMargin: 80; clip: true; model: theModel;//绑定数据源 cellWidth: 45;//设置项大小 cellHeight: 45; delegate: numberDelegate;//设置绘制代理 } //自定义绘制代理 Component { id: numberDelegate; Rectangle { id: wrapper; 40; height: 40; //首先是一个渐变的矩形框 gradient: Gradient { GradientStop { position: 0.0; color: "#f8306a"; } GradientStop { position: 1.0; color: "#fb5b40"; } } //文本值是number的数值 Text { anchors.centerIn: parent; font.pixelSize: 10; text: number;
//text: index;//显示当前序号 } //鼠标点击代理时,移除点击项 MouseArea { anchors.fill: parent; onClicked: { if (!wrapper.GridView.delayRemove)//是否延迟移除 { theModel.remove(index); } } } //GridView移除项 顺序动画 GridView.onRemove: SequentialAnimation { //属性变化 PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: true; } //数字动画 NumberAnimation { target: wrapper;//目标对象 property: "scale";//执行动画的属性 to: 0;//结束值 duration: 250;//动画持续时长 easing.type: Easing.InOutQuad;//动画执行曲线 } PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false; } } //GridView新增项 顺序动画 GridView.onAdd: SequentialAnimation { NumberAnimation { target: wrapper; property: "scale"; from: 0;//开始值 to: 1; duration: 250; easing.type: Easing.InOutQuad; } } } } }
https://zhuanlan.zhihu.com/p/66928607