当前位置:网站首页>Roson的Qt之旅#101 Qt Quick中的模型和视图
Roson的Qt之旅#101 Qt Quick中的模型和视图
2022-07-28 15:12:00 【Allen Roson】
Qt Quick中的模型和视图
简单地说,应用程序需要形成数据并显示数据。Qt Quick有模型、视图和委托的概念来显示数据。它们将数据的可视化模块化,以便让开发者或设计者对数据的不同方面进行控制。开发者可以将列表视图换成网格视图,而对数据没有什么改变。同样,将数据的实例封装在一个委托中,允许开发者决定如何呈现或处理数据。

- 模型:包含数据和它的结构。有几种QML类型用于创建模型。
- 视图:一个显示数据的容器。视图可能在一个列表或网格中显示数据。
- 委托:决定了数据应该如何出现在视图中。委托在模型中获取每个数据并将其封装起来。这些数据可以通过委托来访问。
为了使数据可视化,将视图的模型属性与模型绑定,将委托属性与组件或其他兼容类型绑定。
用视图显示数据
视图是项目集合的容器。它们具有丰富的功能,并且可以定制,以满足风格或行为要求。
在Qt Quick图形类型的基本集合中提供了一组标准视图:
- ListView:在一个水平或垂直的列表中排列项目
- GridView:在可用空间内将项目安排在一个网格中
- PathView:在一个路径上安排项目
这些类型有每个类型独有的属性和行为。
装饰视图
视图允许通过装饰属性(如页眉、页脚和章节属性)进行视觉定制。通过绑定一个对象,通常是另一个视觉对象,到这些属性,视图是可装饰的。一个页脚可能包括一个展示边框的矩形类型,或者一个在列表顶部显示标志的页眉。
假设一个特定的俱乐部想用它的品牌颜色来装饰它的会员列表。一个会员列表在一个模型中,委托将显示模型的内容。
ListModel {
id: nameModel
ListElement { name: "Alice" }
ListElement { name: "Bob" }
ListElement { name: "Jane" }
ListElement { name: "Harry" }
ListElement { name: "Wendy" }
}
Component {
id: nameDelegate
Text {
text: name;
font.pixelSize: 24
}
}
俱乐部可以通过将视觉对象绑定到header和footer属性来装饰成员列表。视觉对象可以被定义在内联,在另一个文件中,或在一个组件类型Component中。
ListView {
anchors.fill: parent
clip: true
model: nameModel
delegate: nameDelegate
header: bannercomponent
footer: Rectangle {
width: parent.width; height: 30;
gradient: clubcolors
}
highlight: Rectangle {
width: parent.width
color: "lightgray"
}
}
Component { //instantiated when header is processed
id: bannercomponent
Rectangle {
id: banner
width: parent.width; height: 50
gradient: clubcolors
border {color: "#9EDDF2"; width: 2}
Text {
anchors.centerIn: parent
text: "Club Members"
font.pixelSize: 32
}
}
}
Gradient {
id: clubcolors
GradientStop { position: 0.0; color: "#8EE2FE"}
GradientStop { position: 0.66; color: "#7ED2EE"}
}
鼠标和触摸操作
视图处理其内容的拖动和滑动,但它们不处理与各个委托的触摸交互。为了让委托对触摸输入做出反应,例如设置currentIndex,必须由委托提供一个具有适当触摸处理逻辑的MouseArea。
请注意,如果highlightRangeMode被设置为StrictlyEnforceRange,currentIndex将受到拖动/滑动视图的影响,因为视图将始终确保currentIndex在指定的高亮范围内。
列表视图部分
ListView的内容可以被分组为部分,相关的列表项根据它们的部分被标记。此外,这些部分可以用代表进行装饰。
列表可以包含一个表示人名和该人所属的团队的列表。
ListModel {
id: nameModel
ListElement { name: "Alice"; team: "Crypto" }
ListElement { name: "Bob"; team: "Crypto" }
ListElement { name: "Jane"; team: "QA" }
ListElement { name: "Victor"; team: "QA" }
ListElement { name: "Wendy"; team: "Graphics" }
}
Component {
id: nameDelegate
Text {
text: name;
font.pixelSize: 24
anchors.left: parent.left
anchors.leftMargin: 2
}
}
ListView类型有section附件属性,可以将相邻和相关的类型组合成一个部分。section.property决定了哪种列表类型的属性可以作为section使用。section.criteria可以决定章节名称的显示方式,section.delegate类似于视图的delegate属性。
ListView {
anchors.fill: parent
model: nameModel
delegate: nameDelegate
focus: true
highlight: Rectangle {
color: "lightblue"
width: parent.width
}
section {
property: "team"
criteria: ViewSection.FullString
delegate: Rectangle {
color: "#b0dfb0"
width: parent.width
height: childrenRect.height + 4
Text { anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: 16
font.bold: true
text: section
}
}
}
}
视图的委托
视图需要一个委托来直观地表示一个列表中的项目。视图将根据委托定义的模板来可视化每个项目列表。一个模型中的项目可以通过索引属性以及项目的属性进行访问。
Component {
id: petdelegate
Text {
id: label
font.pixelSize: 24
text: if (index == 0)
label.text = type + " (default)"
else
text: type
}
}
通过委托访问视图和模型
委托人所绑定的列表视图可以通过ListView.view属性从委托那里访问。同样地,GridView的GridView.view对委托也是可用的。因此,相应的模型及其属性可以通过ListView.view.model获得。此外,模型中任何定义的信号或方法也可以被访问。
当你想对一些视图使用同一个委托,但你希望每个视图的装饰或其他功能不同,并且你希望这些不同的设置成为每个视图的属性时,这种机制很有用。同样地,访问或显示模型的一些属性也可能会引起兴趣。
在下面的例子中,委托显示了模型的属性语言,其中一个字段的颜色取决于视图的属性 fruit_color。
Rectangle {
width: 200; height: 200
ListModel {
id: fruitModel
property string language: "en"
ListElement {
name: "Apple"
cost: 2.45
}
ListElement {
name: "Orange"
cost: 3.25
}
ListElement {
name: "Banana"
cost: 1.95
}
}
Component {
id: fruitDelegate
Row {
id: fruit
Text { text: " Fruit: " + name; color: fruit.ListView.view.fruit_color }
Text { text: " Cost: $" + cost }
Text { text: " Language: " + fruit.ListView.view.model.language }
}
}
ListView {
property color fruit_color: "green"
model: fruitModel
delegate: fruitDelegate
anchors.fill: parent
}
}模型
数据是通过指定的数据角色提供给委托人的,委托人可以与之绑定。这里是一个有两个角色的ListModel,即type和age,以及一个有委托的ListView,它与这些角色绑定以显示它们的值。
import QtQuick 2.0
Item {
width: 200; height: 250
ListModel {
id: myModel
ListElement { type: "Dog"; age: 8 }
ListElement { type: "Cat"; age: 5 }
}
Component {
id: myDelegate
Text { text: type + ", " + age }
}
ListView {
anchors.fill: parent
model: myModel
delegate: myDelegate
}
}
如果模型的属性和委托的属性之间存在命名冲突,可以用合格的模型名称代替角色进行访问。例如,如果Text类型有type或age属性,那么上例中的文本将显示这些属性值,而不是模型项中的type和age值。在这种情况下,这些属性可以被引用为model.type和model.age,以确保委托显示来自模型项的属性值。
一个特殊的索引角色包含了模型中项目的索引,也可以提供给委托人。注意,如果项目从模型中被移除,这个索引将被设置为-1。如果你绑定了索引角色,请确保逻辑上考虑到索引为-1的可能性,也就是说,项目不再有效。(通常项目很快就会被销毁,但是在一些视图中可以通过delayRemove附件属性延迟委托销毁)。
没有命名角色的模型(比如下面所示的ListModel)将通过modelData角色提供数据。modelData 角色也被提供给只有一个角色的模型。在这种情况下,modelData 角色包含与命名角色相同的数据。
QML在内置的QML类型集合中提供了几种类型的数据模型。此外,模型可以用Qt C++创建,然后提供给QQmlEngine供QML组件使用。关于创建这些模型的信息,请访问Using C++ Models with Qt Quick Views和创建QML类型文章。
从一个模型中定位项目可以使用中继器来实现。
列表模型
ListModel是一个在QML中指定的类型的简单层次结构。可用的角色是由ListElement属性指定的。
ListModel {
id: fruitModel
ListElement {
name: "Apple"
cost: 2.45
}
ListElement {
name: "Orange"
cost: 3.25
}
ListElement {
name: "Banana"
cost: 1.95
}
}上述模型有两个角色,名字和费用。这些可以通过ListView委托来绑定,例如:
ListView {
anchors.fill: parent
model: fruitModel
delegate: Row {
Text { text: "Fruit: " + name }
Text { text: "Cost: $" + cost }
}
}ListModel提供了直接通过JavaScript来操作ListModel的方法。在这种情况下,插入的第一个项目决定了使用该模型的任何视图的可用角色。例如,如果一个空的ListModel被创建并通过JavaScript填充,第一次插入提供的角色是将在视图中显示的唯一角色:
ListModel { id: fruitModel }
...
MouseArea {
anchors.fill: parent
onClicked: fruitModel.append({"cost": 5.95, "name":"Pizza"})
}当MouseArea被点击时,fruitModel将有两个角色,cost和name。即使后续的角色被添加,也只有前两个角色会被使用该模型的视图处理。要重置模型中的可用角色,请调用ListModel::clear()。
XML模型
XmlListModel允许从一个XML数据源构建一个模型。角色是通过XmlRole类型指定的。该类型需要被导入。
import QtQuick.XmlListModel 2.0
下面的模型有三个角色,标题、链接和描述。
XmlListModel {
id: feedModel
source: "http://rss.news.yahoo.com/rss/oceania"
query: "/rss/channel/item"
XmlRole { name: "title"; query: "title/string()" }
XmlRole { name: "link"; query: "link/string()" }
XmlRole { name: "description"; query: "description/string()" }
}
查询属性指定XmlListModel为XML文档中的每个<item>生成一个模型项目。
RSS新闻演示展示了XmlListModel如何被用来显示RSS提要。
Object模型
ObjectModel包含要在视图中使用的可视化项目。当ObjectModel被用于视图时,视图不需要委托,因为ObjectModel已经包含了可视化的委托(项目)。
下面的例子在一个ListView中放置了三个彩色的矩形:
import QtQuick 2.0
import QtQml.Models 2.1
Rectangle {
ObjectModel {
id: itemModel
Rectangle { height: 30; width: 80; color: "red" }
Rectangle { height: 30; width: 80; color: "green" }
Rectangle { height: 30; width: 80; color: "blue" }
}
ListView {
anchors.fill: parent
model: itemModel
}
}注意:VisualItemModel也可以被使用,但它只是为了兼容性的原因而提供。VisualItemModel允许一个QML项目作为模型被提供。这个模型包含数据和委托;VisualItemModel的子项目提供委托的内容。该模型不提供任何角色。
以整数作为模型
一个整数可以作为一个包含一定数量类型的模型。在这种情况下,该模型没有任何数据角色。
下面的例子创建了一个有五个元素的ListView。
以对象示例作为模型
一个对象实例可以用来指定一个具有单一对象类型的模型。对象的属性被作为角色提供。
下面的例子创建了一个有一个项目的列表,显示myText文本的颜色。注意使用完全合格的model.color属性以避免与委托中Text类型的color属性发生冲突。
Rectangle {
width: 200; height: 250
Text {
id: myText
text: "Hello"
color: "#dd44ee"
}
Component {
id: myDelegate
Text { text: model.color }
}
ListView {
anchors.fill: parent
anchors.topMargin: 30
model: myText
delegate: myDelegate
}
}
C++数据模型
模型可以用C++定义,然后提供给QML使用。这种机制对于将现有的C++数据模型或其他复杂的数据集暴露给QML很有用。
有关信息,请访问使用C++模型与Qt快速浏览文章。
中继器

中继器使用模型中的数据,从一个模板中创建项目,供定位器使用。结合中继器和定位器是一个简单的方法来布置大量的项目。一个中继器项目被放置在一个定位器内,并生成包围着的定位器所安排的项目。
每个中继器通过将使用模型属性指定的模型中的每个数据元素与定义为中继器内子项目的模板项目结合起来,创建若干项目。项目的总数是由模型中的数据量决定的。
下面的例子显示了一个与网格项一起使用的中继器,用来排列一组矩形项。中继器项创建了一系列24个矩形,供网格项以5乘5的排列方式定位。
import QtQuick 2.0
Rectangle {
width: 400; height: 400; color: "black"
Grid {
x: 5; y: 5
rows: 5; columns: 5; spacing: 10
Repeater { model: 24
Rectangle { width: 70; height: 70
color: "lightgreen"
Text { text: index
font.pointSize: 30
anchors.centerIn: parent } }
}
}
}
中继器创建的项目数量由其count属性持有。不可能通过设置这个属性来确定要创建的项目数量。相反,像上面的例子一样,我们使用一个整数作为模型。
更多细节,请看QML数据模型文档。
如果模型是一个字符串列表,该委托也会暴露在一个只读的modelData属性中,该属性持有字符串。例如:

使用转场
转场可以用来为添加到定位器、在定位器中移动或从定位器中移除的项目制作动画。
添加项目的转场适用于作为定位器的一部分而创建的项目,以及那些被重新赋权成为定位器的子项目。
移除项目的过渡适用于在定位器中被删除的项目,以及从定位器中移除并在文档中获得新父项的项目。
注意:将项目的不透明度改变为零不会导致它们从定位器中消失。它们可以通过改变可见属性被删除和重新添加。
边栏推荐
- Zhaoqi science and technology innovation and entrepreneurship competition talent introduction platform, mass entrepreneurship and entrepreneurship competition high-level talent introduction
- 太阳能路灯的根本结构及作业原理
- How to measure the vibrating wire sensor by vibrating wire acquisition module?
- Stm32f103c8t6 + 0.96 "I2C OLED display 3d_cube
- 动态规划 --- 数位统计DP
- R语言使用GGally包的ggpairs函数可视化分组多变量的两两关系图、设置alpha参数改变图像透明度、对角线上连续变量密度图、离散变量条形图、两两关系图中包含散点图、直方图、箱图以及相关性数值
- js中的for循环总结
- 电压转电流/电流转电压模块
- Use py to automatically generate weekly reports based on log records
- 2021 肯特面试题1
猜你喜欢

12V pulse speed measurement to 24V level signal conversion transmitter

射频模块无线收发RF63U芯片应用数据传输和基建网络

Instructions for mictr01 Tester development kit (vibrating wire acquisition reader)

Is MySQL query limit 1000,10 as fast as limit 10? If I want to page, what should I do?

Common problems and precautions of remote serial port server (adapter) uart/i2c/1-wire/spi PS304

Using SYSTEMd to manage services

Ask if you don't understand, and quickly become an advanced player of container service!

【微信小程序开发(七)】订阅消息

Summary of for loop in JS

CoDeSys realizes bubble sorting
随机推荐
Note: numerical accumulation animation
电压转电流/电流转电压模块
js 数组(总结)
2-channel Di high-speed pulse counter, 1-channel encoder to Modbus TCP wired wireless module ibf161
射频模块无线收发RF63U芯片应用数据传输和基建网络
Basic structure and operation principle of solar street lamp
The deep displacement monitoring system wk813 is used to measure the deep displacement of slopes, dams, embankments, railways and building foundation pit excavation
深入理解Istio流量管理的熔断配置
2021 Kent interview question 3
LabVIEW Linx toolkit controls Arduino equipment (expansion-1)
js 栈
Solve the problem that the right-click menu "edit with idle" of the 『 py 』 file is invalid or missing
Redis系列4:高可用之Sentinel(哨兵模式)
Remote serial port server (adapter) UART to 1-wire application
Telecommuting can be easily realized in only three steps
阿里云的rds mysql 只读实例在哪里创建
Multipurpose mixed signal 8ai/4di/do to serial port rs485/232modbus acquisition module ibf30
R语言ggplot2可视化绘制线图(line plot)、使用gghighlight包突出高亮线图中满足组合判断条件的线图(satisfies both condition A and B)
Knowledge points qwer
头条文章_signature
