模型/视图架构简介
使用 QML 时,有些情况下需要使用模型视图结构显示一些列表等控件,比较好的方式是用 Python 接管数据模型部分,方便处理数据;QML 和 JavaScript 负责前端部分,实现前端和后端的分离。
MVD 简介
Model-View-Controller (MVC) 是源自 SmallTalk 的一个设计模式,在构建用户界面时经常用到。把功能相近的部分归结在一起,不相近的部分进行隔离。MVC 将系统分解为模型、视图、控制器三部分,每一部分相对独立,职责单一,在实现过程中可以专注于 MVC 各自的核心逻辑。MVC 的最基本的作用就是解耦。
模型(Model)代表数据。视图(View)代表界面的布局。控制器(Controller )界面的具体显示样式,和用户进行具体的交互。
QML 对 Controller 部分做了改动,引入了 Delegate,合起来就是 Model-View-Delegate。模型还是负责提供数据,视图则负责基本的布局管理,剩下显示样式由 Delegate 实现。
Model-View-Delegate的框架如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x7tdbq2s-1686869923639)(assets/image-20230601095124-c9x1cqx.png)]
类比到 web 前端,View 提供了布局(html),Delegate 提供了样式(css),model 则提供数据(data),在mvc中, 不仅数据与显示要分离, 在显示中, 布局与样式也要分离, 布局指的是大的框架背景, 元素的排列组合方式和定位模式, 而样式指的是子元素的颜色, 字体, 滤镜等效果。
模型/视图架构中模型(model)、视图(View)和委托(Delegate)之间的关系:
- 模型(model):包含数据及其结构,有多种 QML 类型可以创建模型
- 视图(view):显示数据的容器,数据可以通过列表或者表格形式显示出来
- 委托(delegate):控制数据应该如何在视图中进行显示。委托获取并封装了模型中的每个数据,需要通过委托才能访问到数据
使用样例
为了将数据显示出来,需要将视图的 model 属性绑定到一个模型类型,然后将 delegate 属性绑定到一个组件或者其他兼容的类型
import QtQuick
Item {
width: 200; height: 50、
// 数据模型,将要渲染的数据
ListModel {
id: myModel
ListElement { type: "Dog"; age: 8 }
ListElement { type: "Cat"; age: 5 }
}
// 数据项显示模板,理解为渲染模板
Component {
id: myDelegate
Text { text: type + ", " + age; font.pointSize: 12 }
}
// 数据映射
ListView {
anchors.fill: parent
model: myModel;
delegate: myDelegate
}
}
这里首先创建了一个 ListModel 作为数据模型,然后使用一个 Component 组件作为委托,最后使用 ListView 作为视图,在视图中需要指定模型和委托,如下图的关系:
数据模型
QtQuick 提供的模型主要包括 QtQml.Models
、QtQml.XmlListModels
、TableModel
这几个模块中,它们是 Qt 框架中用于处理数据模型和视图的模块和类。
这些类都是用于在 QML 中处理数据模型的工具,可以与各种 QML 视图类型(如 ListView、GridView、TableView 等)配合使用。通过这些类,开发者可以方便地创建、操作和展示数据,使用户界面与底层数据模型保持同步。无论是静态数据还是动态数据,这些类都为开发者提供了灵活的方式来构建功能强大的交互式应用程序。下面是对它们的简要介绍:
ListModel
ListModel
是一个简单的容器,可以包含 ListElement 类型来存储数据。
QtQml.Models 是 Qt QML 模块中的一部分,提供了一组用于创建和管理数据模型的类。其中最常用的类是 ListModel
,它提供了一种简单的方式来创建基于列表的数据模型。ListModel 可以用于展示静态的数据集合,或者通过 JavaScript 动态地修改和更新数据。ListModel 还支持排序、过滤和分组等常见的数据操作。
QtQml.XmlListModels
QtQml.XmlListModel 是 Qt QML 模块中的另一个类,用于从 XML 数据源中创建数据模型。它可以解析 XML 数据,并将其转换为可供 QML 使用的模型数据。XmlListModel
支持对 XML 数据进行查询和筛选,以便提取所需的数据。这对于从 Web 服务或其他具有 XML 输出的数据源中获取数据非常有用。
TableModel
TableModel 是一个用于创建和管理表格数据模型的自定义类。与 ListModel 不同,TableModel 提供了一种基于表格结构的数据模型。它支持多列数据,并且可以通过自定义的行和列索引来访问和操作数据。TableModel 可以用于展示和编辑具有表格布局的数据集合,例如数据库查询结果。
视图类型
视图类型主要是 Flickable 的几个子类型,包括列表视图 ListView
、网格视图 GridView
、表格视图 TableView
、及其子类型树视图 TreeView
,
在QML中,有多种视图类型可用于将数据呈现给用户。以下是一些常见的QML视图类型:
ListView:
ListView 是一个常用的视图类型,用于在垂直方向上展示可滚动的列表。它可以根据数据模型自动生成多个项目,并支持自定义的项目委托来定义每个项目的外观和交互。ListView 还支持滚动、分页和动画效果等功能。
GridView:
GridView 是一个用于展示网格布局的视图类型。它以二维的方式呈现数据,可以在水平和垂直方向上滚动。GridView 提供了自动布局和调整大小的功能,可以根据项目的尺寸和可用空间自动调整项目的位置和大小。
PathView:
PathView 是一个基于路径的视图类型,可以在指定的路径上展示项目。它可以在曲线、圆形、椭圆等不同的路径上显示项目,并支持滑动、缩放和旋转等动画效果。PathView 可用于创建具有非线性布局的视图,如圆形菜单、旋转木马效果等。
TableView:
TableView 是一个用于展示表格数据的视图类型。它以表格形式显示数据,每个项目位于行和列的交叉点上。TableView 支持水平和垂直滚动,并提供了排序、过滤和编辑等功能,使开发者能够展示和操作结构化的数据。
FlipView:
FlipView 是一个可用于创建可翻页的视图类型。它以水平或垂直方向呈现项目,并支持用户通过滑动手势来翻页。FlipView 可用于创建类似于图片浏览器、书籍阅读器等需要翻页功能的应用程序。
TreeView
TreeView 是一种用于展示分层数据结构的视图类型。它以树形结构的方式呈现数据,每个项目可以包含子项目,从而形成层级结构。TreeView 提供了一种直观的方式来浏览和管理具有父子关系的数据。
ColumnView
ColumnView 是一种用于展示列布局的视图类型。它以垂直列的方式呈现数据,可以实现多列数据的布局和展示。ColumnView 提供了一种灵活的方式来显示和管理具有多列数据的项目。
委托选择器 DelegateChooser
Qt.lab.qmlmodels
模块还提供了一个 DelegateChooser
类型,允许视图对模型中不同类型的项目使用不同的委托。DelegateChooser 中可以封装一组 DelegateChoices
,使用他们可以根据模型数据的不同角色的值或者索引来提供需要的委托项目。
暂时理解为不同场景的不同视图
在 QML 中,DelegateChooser 是一种用于选择和应用项委托的工具。它允许根据某些条件来选择不同的项委托,并将其应用于特定的数据项。它通常与 QML 视图类型(如 ListView、GridView、ColumnView 等)一起使用,以根据条件为每个数据项选择不同的委托。
DelegateChooser 由以下几个关键组件组成:
- DelegateChoice:
DelegateChoice 是 DelegateChooser 的子组件,用于定义一个委托选项。它可以包含一个条件表达式和一个项委托。当条件表达式为真时,DelegateChooser 将选择并应用该项委托。 - DelegateChooser:
DelegateChooser 是一个用于选择和应用项委托的组件。它包含一个或多个 DelegateChoice 子组件。DelegateChooser 会按照它们的顺序评估 DelegateChoice,选择第一个满足条件的委托,并将其应用于对应的数据项。
使用 DelegateChooser 可以根据不同的条件选择和应用不同的项委托,例如根据数据项的类型、属性值或其他自定义条件。这使得可以根据数据的不同特征,为每个数据项选择适当的外观和交互方式。
示例
以下是一个简单的示例,展示如何使用 DelegateChooser 在 ListView 中选择委托:
ListView {
width: 200
height: 400
model: myModel
DelegateChooser {
DelegateChoice {
when: modelData > 10
delegate: Rectangle {
width: 100
height: 50
color: "red"
Text {
text: modelData
color: "white"
anchors.centerIn: parent
}
}
}
DelegateChoice {
when: modelData <= 10
delegate: Rectangle {
width: 100
height: 50
color: "green"
Text {
text: modelData
color: "white"
anchors.centerIn: parent
}
}
}
}
}
在上述示例中,根据模型数据的值,DelegateChooser 选择并应用不同的项委托。当模型数据大于 10 时,选择红色的矩形委托,否则选择绿色的矩形委托。
使用 DelegateChooser 可以根据条件为不同的数据项选择不同的委托,并实现更灵活的视图展示和交互行为。