零、前言
MVC在Qt中叫做MVD,Model+View+Delegate。关于Model,Qt提供了以QAbstractItemModel为父类的相关类。如图:
![](https://i-blog.csdnimg.cn/blog_migrate/00251475409ce1a0c7d1c4a5ca555c0d.png)
①、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{
width: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 {
width: 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{
width: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
width:16
height:16
radius:8
border.color:"black"
border.width: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
width: 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 {
width: 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;
width: 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