零、前言
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{ 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
