QML-Model-View
一、Model-View
1.1、Qt中的model-view是什么
有点类似MVC模式,Qt中,数据通过model-view模式,将数据和显示分离开来
model: 数据模型,负责存储和管理数据view: 视图容器,负责布局和显示管理delegate: 可视化代理,负责单个数据项的可视化呈现
1.2、有哪些view
常见视图组件:
ListView- 列表视图GridView- 网格视图TableView- 表格视图PathView- 路径视图Repeater- 重复器(非视图组件,但常用于重复创建项目)
1.3、Repeater
Repeater是Qt中一个非常有用的组件,它可以重复渲染一组数据。它类似于其他框架中的列表或表格控件,但它的灵活性更高,因为它可以处理任意类型的模型(如字符串、图像等)。
- 属性:
- count: 创建多少项
 - delegate: 每个项的渲染模板
 - model: 数据源
 
 - 信号:
- itemAdded(int index, Item item): 当一个新的项被添加到Repeater时发出。
- onItemAdded(int index, Item item): 处理信号
 
 - itemRemoved(int index, Item item): 当一个项被从Repeater中移除时发出。
- onItemRemoved: 处理信号
 
 
 - itemAdded(int index, Item item): 当一个新的项被添加到Repeater时发出。
 
注意:
Repeater通常会创建其所有delegate项;如果存在大量delegate项,并且并非所有项都必须同时可见,会降低效率,需要考虑其他view
示例代码:
import QtQuick Column{spacing:10Repeater{model: 5delegate: Rectangle{width: 100; height: 50color:"red"}onItemAdded: {console.log("item " + index + "added")}onItemRemoved: {console.log("item" + index + "removed")}}
}
1.4、ListView
类似于Repaeter,只不过delegate之间有间隔,并且可以滑动,所谓的瀑布流布局
关键属性:
spacing: 项间距orientation: 布局方向(默认垂直)clip: 是否裁剪超出区域的内容cacheBuffer: 预渲染缓冲区大小currentIndex: 当前选中项索引highlight: 高亮组件
示例代码:
ListView{anchors.fill: parentanchors.margins: 20spacing: 15clip: true                  // 默认是false,设置为true,在视觉上,会看不见元素创建与销毁的过程model: 100cacheBuffer: 20             // 如果需要展示的元素过多,可以设置缓存区大小,节省频繁创建销毁的内存开销delegate: Rectangle{required property int indexwidth: 20height: 25color: "red"Component.onCompleted: {console.log(index + " added")}Component.onDestruction: {console.log(index + " deleted")}}
}
1.5、GridView
使用GridView可以创建网格布局,类似于ListView,只不过是将delegate布局成网格
关键属性:
cellWidth、cellHeight: 网格大小flow: 布局流向(FlowTopToBottom/FlowLeftToRight)layoutDirection: 布局方向(LeftToRight/RightToLeft)
示例代码:
GridView{anchors.fill: parentclip: truemodel:100cellWidth:40            // 设置每个小网格的长宽cellHeight:40flow:GridView.FlowTopToBottom   // 布局方式是从上到下//flow:GridView.FlowLeftToRight   // 布局方式是从左到右delegate: Rectangle{width: 20height: 20color: "red"}
}
1.6、Delegete
delegate翻译过来是代理,委托的意识;在model-view中,delegate是介于数据和视图之间的桥梁
- 从model获取数据
 - 定义数据可视化方式
 - 响应视图状态变化
 
示例代码:
    ListView{anchors.fill: parentanchors.margins: 20spacing: 15clip: true                  // 默认是false,设置为true,在视觉上,会看不见元素创建与销毁的过程model: 100cacheBuffer: 20             // 如果需要展示的元素过多,可以设置缓存区大小,节省频繁创建销毁的内存开销delegate: numberDelegate}Component{id: numberDelegateRectangle{required property int indexwidth: 40height: 25color: ListView.isCurrentItem ? "black" : "red"id: wrapperText{id:label1text: wrapper.indexanchors.centerIn: parent}}}
delegate动画- onAdd
 - onRemove
 
示例代码:
delegate: Rectangle {required property int index// 添加动画GridView.onAdd: SequentialAnimation {NumberAnimation { property: "scale"; from: 0; to: 1; duration: 300 }}// 移除动画  GridView.onRemove: SequentialAnimation {NumberAnimation { property: "scale"; to: 0; duration: 300 }}
}
二、测试
场景:两个按钮,一个按钮点击,在网格中添加一个元素;另一个按钮点击,删除最后一个元素
import QtQuickRectangle{anchors.fill: parentgradient: Gradient{GradientStop{position:0.0; color:"#dbdbdb"}GradientStop{position:1.0; color:"#5fc9f8"}}// modelListModel{id:theModelListElement{ num:0}ListElement{ num:1}ListElement{ num:2}ListElement{ num:3}}//buttonRectangle{anchors.bottom: parent.bottomanchors.left: parent.leftanchors.right: parent.rightanchors.margins: 20height: 40color: "#53f769"border.color: Qt.lighter(color, 1.1)Text{anchors.centerIn: parenttext: qsTr("add")}MouseArea{anchors.fill: parentonClicked: {theModel.append({"num": theModel.count})console.log(theModel.count)}}}// 删除按钮Rectangle{anchors.bottom: parent.bottomanchors.left: parent.leftanchors.right: parent.rightanchors.margins: 20anchors.bottomMargin: 60  // 在添加按钮上方height: 40color: "#f75353"border.color: Qt.lighter(color, 1.1)Text{anchors.centerIn: parenttext: qsTr("remove last")}MouseArea{anchors.fill: parentonClicked: {if (theModel.count > 0) {theModel.remove(theModel.count - 1)console.log(theModel.count)}}}}// viewGridView{anchors.fill: parentanchors.margins: 20anchors.bottomMargin: 80clip: truecellHeight: 40cellWidth: 60model:theModeldelegate: numberDelegate}// DelegateComponent{id: numberDelegateRectangle{id: wrapperrequired property int indexrequired property int numgradient: Gradient{GradientStop{position:0.0; color:"#dbdbdb"}GradientStop{position:1.0; color:"#5fc9f8"}}width: 40height: 25color: ListView.isCurrentItem ? "black" : "red"Text{id:label1text: qsTr(wrapper.index)anchors.centerIn: parent}// 添加动画GridView.onAdd:addAnimation.start()GridView.onRemove:removeAnimation.start()NumberAnimation{id:addAnimationtarget:wrapperproperty: "scale"from: 0to:1duration: 250easing.type: Easing.InOutQuad}NumberAnimation{id:removeAnimationtarget:wrapperproperty: "scale"to:0duration: 250easing.type: Easing.InOutQuad}}}
}

