在 QML 中,ListView
和 model
是两种非常常用的控件,它们常常用于显示一组数据。model
用于存储数据,而 ListView
用于显示这些数据。特别是当我们处理多层嵌套的 JSON 数据时,理解如何在 QML 中使用 ListView
和 model
是非常重要的。
1. JSON 数据格式
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它具有以下特点:
- 易于阅读和编写。
- 易于机器解析和生成。
JSON 主要由两种结构组成:
- 对象:一组由键值对组成的数据。
- 数组:一组有序的值。
例如,下面是一个描述课程和模块信息的 JSON 示例:
{
"schoolName": "现代编程学院",
"location": "上海",
"courses": [
{
"courseId": 101,
"courseName": "Python 编程基础",
"instructor": "张三",
"duration": 30,
"modules": [
{
"moduleId": 1,
"moduleName": "Python 基础语法",
"time": 10,
"content": "介绍 Python 的基础语法,变量、数据类型和控制流。"
},
{
"moduleId": 2,
"moduleName": "面向对象编程",
"time": 10,
"content": "讲解面向对象的基本概念和如何在 Python 中实现类与对象。"
},
{
"moduleId": 3,
"moduleName": "Python 高级特性",
"time": 10,
"content": "学习 Python 的高级特性,如装饰器、生成器等。"
}
]
},
{
"courseId": 102,
"courseName": "前端开发",
"instructor": "李四",
"duration": 40,
"modules": [
{
"moduleId": 1,
"moduleName": "HTML 基础",
"time": 15,
"content": "介绍 HTML 的基础标签和网页结构。"
},
{
"moduleId": 2,
"moduleName": "CSS 样式",
"time": 15,
"content": "讲解 CSS 的选择器、样式属性以及布局技巧。"
},
{
"moduleId": 3,
"moduleName": "JavaScript 编程",
"time": 10,
"content": "学习 JavaScript 的基本语法、DOM 操作等。"
}
]
}
]
}
2. QML 中的 ListView
和 model
ListView
控件
ListView
是 QML 中用来显示一组数据的控件,它需要一个 model
来提供数据。ListView
会根据模型中的数据生成每个项,并通过 delegate
来指定如何显示这些项。
model
属性
model
是 QML 中存储数据的结构。常见的 model
类型有:
ListModel
:简单的列表模型。XmlListModel
:XML 数据模型。- JSON 数据:可以通过
QVariantMap
和QVariantList
将 JSON 数据传递给 QML。
在我们的例子中,model
是从 C++ 中传递过来的 JSON 数据(通过 QVariantMap
),然后 QML 会读取并展示。
delegate
属性
delegate
是 ListView
用来定义如何展示每一项数据的模板。在 delegate
中,我们使用 modelData
来访问每一项的属性。
3. 如何使用 ListView
和 model
展示 JSON 数据
我们将通过一个简单的例子,展示如何使用 ListView
和 model
来展示上述 JSON 数据。
3.1 显示学校信息和课程
我们有一个包含学校信息和课程列表的 JSON 数据。在 QML 中,我们将用 ListView
展示所有的课程,而每个课程下面的模块列表将使用嵌套的 ListView
来显示。
QML 代码:
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 600
height: 600
title: "课程列表"
// 获取 C++ 传递过来的 QVariantMap
property var school: schoolData
// 显示学校信息
Column {
spacing: 20
anchors.centerIn: parent
Text {
text: "学校名称: " + school.schoolName
font.pointSize: 20
}
Text {
text: "位置: " + school.location
font.pointSize: 16
}
// 显示课程列表
ListView {
width: parent.width
height: 300
model: school.courses
delegate: Item {
width: parent.width
height: 180
Rectangle {
width: parent.width
height: 180
color: "lightblue"
border.color: "blue"
radius: 10
Column {
anchors.centerIn: parent
spacing: 10
Text {
text: "课程名称: " + modelData.courseName
font.pointSize: 18
}
Text {
text: "讲师: " + modelData.instructor
font.pointSize: 14
}
Text {
text: "课程时长: " + modelData.duration + " 小时"
font.pointSize: 14
}
// 显示课程模块列表
ListView {
width: parent.width
height: 100
model: modelData.modules
delegate: Item {
width: parent.width
height: 60
Rectangle {
width: parent.width
height: 60
color: "lightgreen"
border.color: "green"
radius: 5
Column {
anchors.centerIn: parent
spacing: 5
Text {
text: "模块名称: " + modelData.moduleName
font.pointSize: 12
}
Text {
text: "时长: " + modelData.time + " 小时"
font.pointSize: 12
}
Text {
text: "内容: " + modelData.content
font.pointSize: 12
}
}
}
}
}
}
}
}
}
}
}
4. 解析 QML 代码
-
学校信息:
- 在
Column
中,展示学校的名称和位置。我们使用school.schoolName
和school.location
来显示这些信息。
- 在
-
课程列表:
- 使用
ListView
显示school.courses
中的每个课程。每个课程的名称、讲师和课程时长通过modelData
访问。
- 使用
-
模块列表:
- 每个课程内有一个
ListView
,显示该课程的所有模块。模块的名称、时长和内容通过modelData
访问并显示。
- 每个课程内有一个
-
modelData
:modelData
用来访问每一项的数据。在ListView
的delegate
中,modelData
引用当前列表项的数据。
5. 总结
通过上面的例子,我们学会了如何:
- 传递 JSON 数据到 QML:通过 C++ 将 JSON 数据传递给 QML。
- 使用
ListView
展示嵌套数据:通过嵌套的ListView
来展示 JSON 数据中的多层信息(如课程和模块)。 - 使用
modelData
访问数据:通过modelData
访问每一项的数据,确保展示正确的信息。
在 QML 中,ListView
和 model
提供了一种非常灵活和强大的方式来展示多层嵌套的 JSON 数据,只需确保每个层级的数据正确传递并在 delegate
中正确访问。