模型视图结构
模型/视图
模型/视图(Model/View)结构是一种用于分离数据存储和界面展示的编程模式。它提供了一种结构化的方法来管理用户界面和数据交互,确保各组件职责清晰。
结构概述
- 模型(Model) :
- 负责存储和管理数据。
- 提供数据的接口供视图访问。
- 通知视图和代理有关数据变化的信号。
- 视图(View) :
- 负责展示模型中的数据。
- 将用户界面和模型的数据进行绑定。
- 自动更新以反映模型数据的变化。
- 代理(Delegate) :
- 负责在视图中编辑模型的数据。
- 提供自定义数据编辑的接口。
这种结构的关键在于实现:
- 数据与界面的分离 :
- 模型处理数据,视图负责显示。
- 视图仅通过模型的接口访问数据。
- 自动更新机制 :
- 模型中的数据变更会自动通知视图更新显示。
- 灵活的视图/模型组合 :
- 可以使用多种视图展示相同的模型。
模型/视图结构基本原理
模型/视图架构是一种用于分离界面和数据的机制。这种架构能够很好地维护数据和表示之间的独立性,常用于数据库应用程序,因为它允许数据以灵活、强大的方式在用户界面组件和后端之间传递。
模型/视图架构的设计理念:
- 分离界面和原始数据 :
- 数据直接存储在模型中(通常来自数据库等)。
- 界面(视图)仅负责显示数据,不直接操作它。
- 模型的作用 :
- 模型是数据和视图之间的桥梁。
- 模型代表了数据的逻辑结构,可以是表格、树、列表等结构。
- 视图的作用 :
- 负责将模型中的数据展示给用户。
- 用户可以通过视图直观地查看、编辑、操作数据。
- 控制器 (在 Qt 的实现中通常是槽函数):
- 通过信号与槽机制完成模型和视图间的通信。
- 修改后的数据通过模型传递到数据库等原始源。
在Qt中如何处理这些关系:
数据 (Source Data)
- 数据源可能是内存中的字符串列表、二维表、数据库表,甚至是磁盘文件的数据。
- 数据只存储在后台,与视图分离。
模型 (Model)
- 负责与数据源的通信,提取需要显示的数据,并提供给视图进行展示。
- 模型是视图间接访问数据的桥梁。
- Qt 提供了一些标准模型类:
- QStringListModel :处理字符串列表数据。
- QStandardItemModel :处理通用的表格型数据。
- QSqlTableModel :用于数据库表数据。
视图 (View)
- 是用户界面的显示组件。
- 从模型中获取数据,并呈现在用户界面上。
- Qt 提供了一些标准视图类:
- QListView :显示列表型数据。
- QTreeView :显示树型数据。
- QTableView :显示表格型数据。
代理 (Delegate)
- 用于在视图中编辑模型数据的临时编辑器。
- 自定义代理可以设置专用的编辑器组件(如使用滑块 QSlider 编辑表格数据中的数值)。
- 通常提供数据的展示和编辑方案(如使用 QItemDelegate 或 QStyledItemDelegate )。
信号与槽 (Signals and Slots)
- 模型和视图通过信号与槽通信。
- 当数据发生变化时:
- 模型发出信号通知视图更新。
- 当用户通过视图操作数据时:
- 视图发出信号通知模型更新数据。
- 代理也通过信号与槽与模型和视图之间互动。
由于显示与数据源,编辑分离:
- 可以将一个模型在不同的视图中显示
- 为特殊数据源设计自定义模型
- 为数据设计特殊的视图
模型
所有基于项(item)的模型类都是从 QAbstractItemModel 类派生的。这个类定义了视图组件和代理访问数据的接口。
- 模型的作用 :
- 模型类用于临时存储数据。
- 数据来源可以是其他类、文件、数据库或者任何数据源。
- 继承 :
- QAbstractItemModel 是从 QObject 继承的。
- 由于继承了 QObject ,模型类支持 Qt 的元对象系统。
- 主要特性 :
- 提供了视图和数据之间的接口。
- 支持信号与槽机制,便于数据变动的实时响应。
QAbstractItemModel 不能直接用于创建实例对象。
常用类型类
| 模型类名称 | 描述 |
|---|---|
| QFileSystemModel | 用于展示文件系统结构的模型。它允许你以树状结构浏览文件系统中的文件和目录。这个模型主要用于图形界面的文件浏览器或资源管理器中。 |
| QStringListModel | 一个简单的模型,用于展示字符串列表。通常用于简单的列表视图,比如用于展示列表项的简单列表视图控件。 |
| QStandardItemModel | 提供了一种灵活的方式来存储和操作数据模型。它是一个标准的表模型,允许你创建自定义的数据结构并展示在视图控件中。这个模型提供了许多有用的方法和功能,用于处理复杂的表结构。 |
| QSqlQueryModel | 用于数据库查询结果的模型。它封装了数据库查询的结果,使得你可以在视图控件中展示这些结果。它简化了与数据库的交互过程,特别是在处理大量数据的时候。 |
| QSqlTableModel | 一个更加专门的数据库模型,通常用于创建和维护数据库的表结构。它可以提供对数据库表的读写访问,并允许你直接在模型中编辑数据,然后同步到数据库中。这对于创建基于数据库的界面非常有用。 |
视图
视图就是用于显示模型中的数据的界面组件,Qt提供的视图组件主要有以下几个。
| 视图组件名称 | 描述 | 适用数据类型 |
|---|---|---|
| QListView | 用于显示单列的列表数据。 | 一维数据(列表形式) |
| QTreeView | 用于显示树状结构数据。 | 树状结构数据(如文件夹和文件) |
| QTableView | 用于显示表格数据,包括行和列的二维数据。 | 二维表格数据(如数据库表或电子表格) |
| QColumnView | 用多个 QListView 显示树状结构数据,每一层用一个 QListView 显示。 | 树状结构数据(分层展示) |
| QUndoView | 用于显示 undo 指令栈内数据的视图组件,是 QListView 的子类。 | Undo 指令栈内的数据(操作历史记录等) |
QListWidget 、 QTreeWidget 和 QTableWidget 这三个是用于处理项数据的组件。它们分别是三个视图类的子类,也叫视图类的便利类。
视图类的使用:
- 视图类通过 setModel() 函数与模型连接来显示数据。
- 视图组件直接与模型交互,在视图中修改数据时会更新模型。
- 都不直接存储数据,数据的展示和修改由模型处理。
便利类的特点:
- 便利类不使用模型,而是通过项(如 QTableWidgetItem )来存储数据。
- 为每个节点或单元格创建一个项,用项来替代模型的功能。
适用范围:
- 便利类适用于小型数据的展示和编辑。
- 没有模型,用项的方式代替模型的功能。缺乏处理大型数据源的灵活性。
- 相比之下,视图组件通过模型来处理数据,更灵活且适合大型数据源。
示例:使用便利类。 QTableWidget 作为便利类将数据直接存储在 QTableWidgetItem 中,每个单元格有自己的数据对象。这种方式适合小型数据集
cpp
#include <QApplication>
#include <QTableWidget>
#include <QTableWidgetItem>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QTableWidget tableWidget(3, 2); // 3行2列
// 设置数据
tableWidget.setItem(0, 0, new QTableWidgetItem("Item 0,0"));
tableWidget.setItem(0, 1, new QTableWidgetItem("Item 0,1"));
tableWidget.setItem(1, 0, new QTableWidgetItem("Item 1,0"));
tableWidget.setItem(1, 1, new QTableWidgetItem("Item 1,1"));
tableWidget.setItem(2, 0, new QTableWidgetItem("Item 2,0"));
tableWidget.setItem(2, 1, new QTableWidgetItem("Item 2,1"));
tableWidget.show();
return app.exec();
}
示例:模型/视图框架,适合处理大型和动态数据。 QStandardItemModel 用作数据模型, QTableView 显示其数据。任何在视图中的更改都会自动更新到模型中
cpp
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QTableView tableView;
QStandardItemModel model(3, 2); // 3行2列
// 设置数据
model.setItem(0, 0, new QStandardItem("Item 0,0"));
model.setItem(0, 1, new QStandardItem("Item 0,1"));
model.setItem(1, 0, new QStandardItem("Item 1,0"));
model.setItem(1, 1, new QStandardItem("Item 1,1"));
model.setItem(2, 0, new QStandardItem("Item 2,0"));
model.setItem(2, 1, new QStandardItem("Item 2,1"));
tableView.setModel(&model);
tableView.show();
return app.exec();
}
代理
代理用于在视图组件中为数据编辑提供临时编辑器。它负责在视图和模型之间协调数据的展示和编辑操作。
QAbstractItemDelegate 是所有代理类的基类,不能直接使用。
常用的代理类有 QItemDelegate 和 QStyledItemDelegate 。
对于特殊编辑需求,可以通过继承 QStyledItemDelegate 创建自定义代理类。
代理的作用
- 编辑器的提供:代理负责在视图组件(如 QTableView )上为数据编辑提供临时编辑器,例如默认情况下单元格数据的编辑器是 QLineEdit 。
- 数据的处理:从模型获取数据,显示在编辑器中。
- 在编辑完成后,将编辑器中修改后的数据保存回模型。
代理类的继承结构
- 基类:QAbstractItemDelegate抽象类,不能直接用于创建代理对象。
- 子类:QItemDelegate :功能基本与 QStyledItemDelegate 相同。QStyledItemDelegate :默认代理类。
- 支持使用 Qt 样式表绘制代理组件。
特殊需求处理
- 通过为视图组件设置自定义代理,可以实现特殊数据编辑需求:例如:
- 只允许输入整数时,可用 QSpinBox 作为代理组件。
- 数据需从预设列表中选择时,可用 QComboBox 作为代理组件。
- 可通过继承 QStyledItemDelegate 创建自定义代理类,根据需求配置特殊的编辑器或行为。
模型/视图结构相关概念
在模型/视图框架中,模型为视图组件和代理提供了存取数据的接口,通过统一的模型结构完成了数据展示与交互方式的分离。
模型中的数据存储单元是以 项 (item) 为基本单位,每个项由行号、列号和父项定义,同时通过 模型索引 (QModelIndex) 作为临时指针来存取数据。
模型的基本结构
- 基类与继承:
- QAbstractItemModel 是所有模型类的基类。
- 其子类将底层数据组织成特定的表格层次结构,不论实际的数据结构如何。
- 常见模型结构:
- 列表模型 (list model):数据存储为单列。
- 表格模型 (table model):数据存储为二维规则表格(行和列的结构)。
- 树状模型 (tree model):数据存储为有父子关系的树状结构(复杂结构,每个节点可能有子节点)。
- 数据项的组成:
- 每个数据项由 行号 和 列号 唯一标识。
- 每个项有一个 父项 (parent item)。
- 模型都包含一个隐藏的 根项 (root item),作为数据结构的起点。
模型索引
- 作用:
- 模型索引用来表示与模型中的一个数据项对应的临时指针。
- 视图组件 和 代理 使用模型索引与模型交互来获取或修改数据。
- 特点:
- 通过 QModelIndex 表示模型索引,模型索引包含行号、列号以及父项索引。
- 唯一性: 每个数据项有一个唯一的模型索引。
- 临时性: 模型的数据结构可能随时变化,因此,模型索引是临时的,数据被修改后可能失效。
- 使用场景:
- 例如在 QTreeView 组件中,获取某节点的模型索引后,若模型发生改变,则之前的模型索引可能无效。
行号与列号
- 作用:
- 模型的基本形式是以 行号 和 列号 为标准的表格数据模型,为界面组件间的数据交互提供统一标准。
- 参数构成:
- 一个模型索引需要以下 3 个参数:
- 行号
- 列号
- 父项的模型索引
- 一个模型索引需要以下 3 个参数:
- 说明:
- 模型底层未必用二维数组存储数据,行号和列号仅用于简化访问方式。
- 例如表格模型中的项 A、B、C 的示例:,通过 (行号, 列号, 父项索引) 来获取其模型索引。
父项
- 概念:
- 所有项都有一个父项,顶层项的父项为隐藏的根项( root item )。
- 结构特性:
- 列表模型或表格模型:父项通常是顶层项,所有项共享一个共同的父项。
- 树状模型:每个节点都有一个父节点,同时可能作为其他节点的父节点。构造节点的模型索引时,必须提供行号、列号以及父节点的索引。
项的角色
- 定义:
- 数据项( item )的每个角色对应一组数据,角色由 Qt 的角色枚举常量定义。
- 设置数据:
- setData() 函数用于为模型的某项设置数据。
- 数据可根据不同的角色被多次设置:如: Qt::EditRole (编辑用数据)、 Qt::DecorationRole (装饰用数据,如图标)等。
抽象类
QAbstractltemModel类
QAbstractltemModel是所有模型类的直接或间接父类
- 它定义了模型的通用接口函数,例如用于插入行、删除行、设置数据的函数。
- QAbstractItemModel是抽象类,不能直接用于创建对象实例,各个具体的模型类实现了这些接口函数。这个模型类是所有其他特定模型的基类,例如 QStandardItemModel 、 QStringListModel 等。
在 Qt 中,模型用于管理数据以及与视图(如 QListView 、 QTreeView 等)之间的数据交互。模型提供了数据展示的核心逻辑和视图所需要的数据。视图负责展示模型的数据和用户交互。
QAbstractItemModel 提供了一个通用的接口,使得开发者可以创建自定义的模型来满足特定的数据展示需求。它定义了基本的模型功能,如数据的索引访问、数据行数、列数等。此外,它还定义了一些基本的操作,如添加和删除行或列等。具体的实现则由继承自 QAbstractItemModel 的子类来完成。子类通常包含数据的实际存储和处理逻辑。
QAbstractItemModel 的重要特性:
- 索引访问:模型通过索引来访问数据。每个索引指向模型中的一个特定位置(行和列)。这允许视图高效地访问和更新数据。
- 数据角色:模型定义了不同的数据角色(如文本、图标等),这些角色用于描述模型中数据的不同属性。视图可以通过这些角色来获取或设置数据。
- 信号与槽:模型通过发出信号来通知视图数据的改变,比如数据添加或删除。这使得视图可以实时响应模型的改变并更新界面。
- 可定制性:由于它是一个抽象类,开发者可以扩展它并实现自定义的数据存储和逻辑处理来满足特定应用的需求。这包括数据的过滤、排序等高级功能。
QAbstractltemView类
QAbstractItemView 是 Qt 框架中的一个抽象类,它提供了实现列表或表格类视图的接口。
这个类是各种具体视图类(如 QListView 、 QTableView 和 QTreeView )的基础,并为这些类提供了核心的功能和数据管理逻辑。
主要功能和特点:
- 数据模型管理: QAbstractItemView 用来显示模型数据(例如,由 QAbstractItemModel 或其子类提供的模型数据)。它将用户界面与模型分离,允许开发人员使用模型-视图-委托(Model-View-Delegate)架构来管理数据的展示和编辑逻辑。
- 支持编辑操作:用户可以在某些类型的单元格(例如在 QTableView 中的单元格)中进行编辑操作, QAbstractItemView 提供了一种机制来处理这些编辑操作。它允许开发者定义哪些单元格是可编辑的,并处理编辑事件。
- 自定义布局:尽管 QAbstractItemView 为不同种类的视图提供了预定义的布局(如列表、表格和树状结构),但它也允许开发者通过继承这个类来创建自定义的视图布局。这使得开发者可以根据特定需求定制视图的外观和行为。
- 键盘导航和快捷键处理:它处理用户的键盘输入事件来导航数据和选择项。这意味着用户可以轻松地通过键盘来浏览列表或表格数据。
- 数据排序和筛选:提供了对数据进行排序和筛选的方法,这有助于根据不同的需求和优先级对数据进行展示和管理。例如,在 QTableView 中可以按某一列进行排序,或者根据特定的条件过滤数据。
使用示例:
QAbstractItemView 是一个抽象类不能直接使用,但通过其子类如 QListView 或 QTableView ,可以轻松实现一个基础的列表或表格视图。
例如,在 QTableView 中,你可以创建一个模型来存储数据,然后将这个模型与视图关联起来,从而展示数据给用户。此外,你还可以自定义视图的外观和行为,比如使用委托来定义单元格的编辑方式或展示样式等。
示例:如何使用 QTableView 和 QStandardItemModel 来创建和显示一个表格视图。
cpp
//用 QStandardItemModel 存储一些数据,并将其关联到 QTableView。
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 创建一个 QStandardItemModel,3 行 3 列
QStandardItemModel model(3, 3);
// 设置模型中的数据
for (int row = 0; row < 3; ++row) {
for (int column = 0; column < 3; ++column) {
QStandardItem *item = new QStandardItem(QString("Row %1, Column %2").arg(row).arg(column));
model.setItem(row, column, item);
}
}
// 创建 QTableView
QTableView tableView;
tableView.setModel(&model); // 将模型关联到视图
// 显示视图
tableView.show();
return app.exec();
}
解释
- QApplication: 应用程序对象,负责管理应用程序的控制流和主要设置。
- QStandardItemModel: 用于存储数据的模型,具有3行3列的表格。
- QStandardItem: 用来填充模型的数据项,文本格式为 "Row X, Column Y"。
- QTableView: 用于显示模型数据的视图。
- setModel: 关联模型和视图,将数据呈现到界面上。
QAbstractItemDelegate类
QAbstractItemDelegate 是 Qt 框架中的一个重要类,它位于信号与槽和视图/模型之间。它是用于创建自定义数据编辑功能的基类,允许用户自定义如何在视图控件中渲染和编辑模型中的数据。
以下是关于 QAbstractItemDelegate 的简要介绍:
主要功能:
- 渲染数据:定义如何渲染或显示模型中的数据。这意味着您可以控制视图中的单元格、行或任何其他数据单元如何显示。
- 编辑数据:定义如何编辑模型中的数据。当用户点击一个单元格并尝试编辑其内容时,可以使用 QAbstractItemDelegate 来提供一个自定义的编辑器。
主要特点:
- 它提供了一个接口来定义如何在视图中显示和编辑模型中的项。这意味着你可以为列表、表格或其他任何视图控件创建自定义的渲染和编辑行为。
- 它允许创建复杂的编辑器,如自定义对话框或复杂的表单,用于编辑模型中的特定数据。
- 它允许开发者创建具有丰富界面和数据验证逻辑的视图控件。例如,开发者可以验证输入的数据是否符合特定的格式或条件。
使用示例:
当你想为 QTableView 或 QListView 中的某个特定列创建自定义编辑器时,你可以继承 QAbstractItemDelegate 并重写其方法(如 createEditor , setEditorData , setModelData 等)。然后,你可以将这个自定义委托应用到视图控件的特定列或行上。这样,当用户尝试编辑该列或行的数据时,将使用你的自定义编辑器而不是标准的单元格编辑器。
QStringListModel 和 QListView
QStringListModel
- 功能: 用于存储和管理字符串列表。
- 接口: 提供添加、删除、修改字符串的方法。
- 自动更新: 修改模型的数据后,视图会自动反映更新的内容。
QListView
- 功能: 用于显示和编辑模型中的数据。
- 默认代理: 支持使用 QLineEdit 进行字符串编辑。
- 职责: 仅作数据显示和编辑,不直接修改数据。
应用场景
- 用于创建简单的字符串列表编辑界面。
- 适用于需要实时更新和反馈的应用。
QStringListModel
QStringListModel是管理字符串列表数据的模型类,与 QListView组件搭配组成模型/视图结构,适合处理字符串列表数据。
- 它主要用于为基于 Qt 的应用程序提供数据模型,尤其是在需要展示一行行文本数据的情况下。
- 这个模型是为 QListView 或其他基于模型的视图控件设计的,以便在这些控件中展示字符串列表。
主要特点:
- 存储字符串列表: QStringListModel 用于存储一系列的字符串数据。这些字符串可以是任何文本形式,例如列表中的项目、文件的名称等。
- 简单的数据模型:相对于其他更复杂的模型(如 QStandardItemModel ), QStringListModel 是一个简单的模型,它主要关注于字符串列表的展示。它提供了插入、删除和修改字符串的基本方法。
- 与视图控件配合使用: QStringListModel 通常与 QListView 或其他基于模型的视图控件一起使用,以展示数据给用户。这使得数据的展示更加灵活和易于管理。
- 基本的CRUD操作:这个模型提供了创建(Create)、读取(Read)、更新(Update)和删除(Delete)操作的基本实现,以管理字符串列表中的数据。
示例:如何使用 QStringListModel 与 QListView 结合
cpp
#include <QApplication>
#include <QListView>
#include <QStringListModel>
#include <QVBoxLayout>
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建主窗口
QWidget window;
window.setWindowTitle("QStringListModel Example");
// 创建布局
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建字符串列表模型
QStringListModel *model = new QStringListModel();
// 初始化数据
QStringList stringList;
stringList << "Apple" << "Banana" << "Cherry";
model->setStringList(stringList);
// 创建 QListView
QListView *listView = new QListView();
listView->setModel(model); // 设置模型
// 创建输入框和按钮用于添加新项
QLineEdit *lineEdit = new QLineEdit();
QPushButton *addButton = new QPushButton("Add Item");
// 连接按钮点击信号与添加项功能
QObject::connect(addButton, &QPushButton::clicked, [&]() {
QString newItem = lineEdit->text();
if (!newItem.isEmpty()) {
model->insertRow(model->rowCount()); // 在最后一行插入新项
model->setData(model->index(model->rowCount() - 1), newItem); // 设置数据
lineEdit->clear(); // 清空输入框
}
});
// QObject::connect(addButton, &QPushButton::clicked, [&]() {
// QString newItem = lineEdit->text();
// if (!newItem.isEmpty()) {
// int row = model->rowCount(); // 获取当前行数作为新行索引
// model->insertRow(row); // 在末尾插入
// model->setData(model->index(row), newItem); // 使用保存的索引
// lineEdit->clear();
// }
// });
// QObject::connect(addButton, &QPushButton::clicked, [&]() {
// QString newItem = lineEdit->text();
// if (!newItem.isEmpty()) {
// QStringList currentList = model->stringList();
// currentList.append(newItem);
// model->setStringList(currentList); // 一次性设置
// lineEdit->clear();
// }
// });
// QObject::connect(addButton, &QPushButton::clicked, [&]() {
// QString newItem = lineEdit->text();
// if (!newItem.isEmpty()) {
// int row = model->rowCount();
// model->insertRow(row);
// QModelIndex index = model->index(row); // 明确获取索引
// model->setData(index, newItem);
// lineEdit->clear();
// }
// });
// 将组件添加到布局
layout->addWidget(listView);
layout->addWidget(lineEdit);
layout->addWidget(addButton);
window.setLayout(layout);
window.resize(300, 200);
window.show();
return app.exec();
}
代码解析
- 创建 QApplication:初始化 Qt 应用程序。
- 创建主窗口:使用 QWidget 创建主窗口,并设置标题。
- 布局:使用 QVBoxLayout 创建垂直布局,以便容纳列表和输入控件。
- 创建 QStringListModel :
- 实例化模型,并设置初始字符串列表(例如 "Apple"、"Banana" 和 "Cherry")。
- **创建 QListView **:用于显示字符串列表,并将模型与视图连接。
- 输入框和按钮:
- 使用 QLineEdit 创建一个输入框和 QPushButton 按钮,允许用户添加新项。
- 连接按钮点击信号到一个 lambda 函数,输入框内容不为空时,插入新项到模型中。
- 布局添加:将 QListView、输入框和按钮添加到布局中,并设置为主窗口的布局。
- 显示窗口:设置窗口大小并显示主窗口。
运行结果:

QListView
QListView 是用于显示列表数据的视图组件,适合展示简单的项集合。它支持许多样式、选择方式以及与模型(如 QStringListModel )的结合使用。
主要特性
- 单列展示:适合显示单列数据,可以按行排列。
- 模型/视图架构:使用 Model/View 架构,与模型(如 QStandardItemModel 或 QStringListModel )协同工作。
- 自定义项:支持自定义数据项和渲染。
- 支持选择:允许单选或多选模式,用户可以选择列表中的一个或多个项。
使用方法
- **创建 QListView **:实例化 QListView 对象。
- 设置模型:将数据模型(如 QStringListModel )与 QListView 连接。
- 配置选择模式:可配置行或复选框选择。
- 添加和更新数据:通过模型的方法来增加、修改或删除项。
示例:使用 QListView 和 QStringListModel
cpp
#include <QApplication>
#include <QListView>
#include <QStringListModel>
#include <QVBoxLayout>
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建主窗口
QWidget window;
window.setWindowTitle("QListView Example");
// 创建布局
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建 QStringListModel
QStringListModel *model = new QStringListModel();
// 初始化数据
QStringList items;
items << "Item 1" << "Item 2" << "Item 3";
model->setStringList(items);
// 创建 QListView
QListView *listView = new QListView();
listView->setModel(model); // 设置模型
// 创建输入框和按钮用于添加新项
QLineEdit *lineEdit = new QLineEdit();
QPushButton *addButton = new QPushButton("Add Item");
// 连接按钮点击信号与添加项功能
QObject::connect(addButton, &QPushButton::clicked, [&]() {
QString newItem = lineEdit->text();
if (!newItem.isEmpty()) {
model->insertRow(model->rowCount()); // 在最后一行插入新项
model->setData(model->index(model->rowCount() - 1), newItem); // 设置数据
lineEdit->clear(); // 清空输入框
}
});
// 将组件添加到布局
layout->addWidget(listView);
layout->addWidget(lineEdit);
layout->addWidget(addButton);
window.setLayout(layout);
window.resize(300, 200);
window.show();
return app.exec();
}
代码解析
- 创建 QApplication:初始化 Qt 应用程序。
- 创建主窗口:使用 QWidget 创建主窗口,并设置窗口标题。
- 布局:使用 QVBoxLayout 创建垂直布局,以便容纳列表和输入控件。
- 创建 QStringListModel :
- 实例化模型,并设置初始字符串列表(例如 "Item 1"、"Item 2" 和 "Item 3")。
- **创建 QListView **:用于显示字符串列表,并将模型与视图连接。
- 输入框和按钮:
- 使用 QLineEdit 创建一个输入框和 QPushButton 按钮,允许用户添加新项。
- 连接按钮点击信号到 lambda 函数,输入框内容不为空时,插入新项到模型中。
- 布局添加:将 QListView 、输入框和按钮添加到布局中,并设置为主窗口的布局。
- 显示窗口:设置窗口大小并显示主窗口。
运行结果:

QStandardItemModel和 QTableView
QStandardItemModel:
- 基于项的模型类。通用模型,支持树状结构和表格数据。
- 存储二维数据,项为 QStandardItem 对象。
- 保存文字、字体、对齐方式等角色的数据。
QTableView:
- 二维表格视图组件。
- 每个单元格显示模型中的一个项。
- setModel() 函数用于设置数据模型。
QItemSelectionModel:
- 项选择模型类。
- 跟踪视图组件的单元格选择状态。
- 获取选中单元格的模型索引。
QStandardItemModel
QStandardItemModel 是 Qt 6 中一个非常方便的模型类,适用于存储和管理简单的数据项。它支持多种数据类型和层级结构,适合用于 QListView 、 QTreeView 和 QTableView 等视图组件。
主要特性
- 层级结构:支持树形结构,可以创建父子项。
- 多种数据类型:支持存储文本、图像和复选框等多种类型的数据。
- 方便的API:提供丰富的方法来插入、更新和删除数据项。
使用方法
- **创建 QStandardItemModel **:实例化模型并设置行和列数。
- 添加数据项:使用 QStandardItem 来创建和管理数据项。
- 连接视图:将模型与视图(如 QListView 或 QTreeView )连接。
示例:如何使用 QStandardItemModel 和 QTreeView 来创建一个简单的树型视图。
cpp
#include <QApplication>
#include <QTreeView>
#include <QStandardItemModel>
#include <QVBoxLayout>
#include <QWidget>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建主窗口
QWidget window;
window.setWindowTitle("QStandardItemModel Example");
// 创建布局
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建 QStandardItemModel
QStandardItemModel *model = new QStandardItemModel();
model->setColumnCount(2); // 设置两列
model->setHeaderData(0, Qt::Horizontal, "Item Name");
model->setHeaderData(1, Qt::Horizontal, "Description");
// 添加根项
QStandardItem *rootItem = model->invisibleRootItem();
// 添加第一个子项
QStandardItem *item1 = new QStandardItem("Item 1");
item1->setData("This is Item 1", Qt::ToolTipRole); // 设置提示信息
rootItem->appendRow(item1);
// 添加第二个子项及其子项
QStandardItem *item2 = new QStandardItem("Item 2");
rootItem->appendRow(item2);
QStandardItem *subItem = new QStandardItem("Sub Item 2.1");
item2->appendRow(subItem); // 将子项添加到 Item 2
// 添加更多项
QStandardItem *item3 = new QStandardItem("Item 3");
rootItem->appendRow(item3);
// 创建 QTreeView
QTreeView *treeView = new QTreeView();
treeView->setModel(model); // 设置模型
treeView->expandAll(); // 展开所有项
// 将组件添加到布局
layout->addWidget(treeView);
window.setLayout(layout);
window.resize(400, 300);
window.show();
return app.exec();
}
代码解析
- 创建 QApplication:初始化 Qt 应用程序。
- 创建主窗口:使用 QWidget 创建主窗口,并设置窗口标题。
- 布局:使用 QVBoxLayout 生成垂直布局。
- 创建 QStandardItemModel :
- 实例化模型,设置列数,并为列设置表头。
- 添加数据项:
- 获取根项,并创建多个子项,设置其数据及提示信息。
- 使用 appendRow 方法将子项添加到父项。
- **创建 QTreeView **:用于显示层级结构的数据模型,并将模型与视图连接。
- 展开所有项:使用 expandAll() 方法使视图展示所有项。
- 布局添加:将 QTreeView 添加到布局并设置为主窗口的布局。
- 显示窗口:设置窗口大小并显示主窗口。
运行结果:

QTableView
QTableView 是 Qt 6 中用于显示表格数据的视图类,它与模型相结合使用,可以显示和编辑二维数据结构。与 QStandardItemModel 或自定义模型结合使用,可以轻松管理和展示数据。
主要特性
- 数据展示:适合展示行列结构的数据。
- 可编辑:支持直接在视图中编辑数据。
- 数据排序:支持排序和过滤数据。
- 自定义绘制:可以通过代理类自定义单元格的外观。
使用方法
- **创建 QTableView ** 视图。
- 创建数据模型(如 QStandardItemModel )。
- 将模型设置到视图。
- (可选)设置代理以自定义单元格的显示和编辑行为。
示例:如何使用 QTableView 和 QStandardItemModel 来创建一个简单的表格应用。
cpp
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QVBoxLayout>
#include <QWidget>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建主窗口
QWidget window;
window.setWindowTitle("QTableView Example");
// 创建布局
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建 QStandardItemModel
QStandardItemModel *model = new QStandardItemModel(4, 3); // 4行3列
model->setHorizontalHeaderLabels({"Name", "Age", "Occupation"}); // 设置表头
// 填充模型数据
model->setItem(0, 0, new QStandardItem("Alice"));
model->setItem(0, 1, new QStandardItem("30"));
model->setItem(0, 2, new QStandardItem("Engineer"));
model->setItem(1, 0, new QStandardItem("Bob"));
model->setItem(1, 1, new QStandardItem("25"));
model->setItem(1, 2, new QStandardItem("Designer"));
model->setItem(2, 0, new QStandardItem("Charlie"));
model->setItem(2, 1, new QStandardItem("35"));
model->setItem(2, 2, new QStandardItem("Manager"));
model->setItem(3, 0, new QStandardItem("Diana"));
model->setItem(3, 1, new QStandardItem("28"));
model->setItem(3, 2, new QStandardItem("Artist"));
// 创建 QTableView
QTableView *tableView = new QTableView();
tableView->setModel(model); // 关联模型
// 设置单元格可编辑
for (int row = 0; row < 4; ++row) {
for (int col = 0; col < 3; ++col) {
QStandardItem *item = new QStandardItem("Editable");
item->setFlags(item->flags() | Qt::ItemIsEditable); // 设置为可编辑
model->setItem(row, col, item);
}
}
// 将组件添加到布局
layout->addWidget(tableView);
window.setLayout(layout);
window.resize(400, 300);
window.show();
return app.exec();
}
代码解析
- 创建 QApplication:初始化 Qt 应用程序。
- 创建主窗口:使用 QWidget 创建窗口,并设置标题。
- 布局:使用 QVBoxLayout 创建布局。
- 创建数据模型:
- 实例化 QStandardItemModel ,设置行数和列数。
- 使用 setHorizontalHeaderLabels 方法设置表头。
- 使用 setItem 方法填充模型数据。
- 创建 QTableView:
- 实例化 QTableView ,并通过 setModel 方法将模型与视图连接。
- 设置编辑策略:使用 setEditStrategy 设置为 OnFieldChange ,表示在单元格内容改变时立即保存。
- 布局添加:将 QTableView 添加到布局中。
- 显示窗口:设置窗口大小并显示。
运行结果:

QStandardItem
QStandardItem 是 Qt 6 中的一个用于构建模型中单个项的类,常与 QStandardItemModel 一起使用。它允许存储多种数据格式,可以设置各种属性,例如图标、字体、文本颜色等,适合构建简单和复杂的树形或表格数据结构。
主要特性
- 多类型数据:支持存储不同类型的数据,如文本、图像等。
- 自定义属性:可设置图标、字体、背景色等属性。
- 层级结构:可以创建层级结构的项目,如树形视图。
- 可编辑性:支持编辑内容、复制、粘贴等操作。
使用方法
- 创建 QStandardItem 对象。
- 为项目设置属性(如文本、图标等)。
- 将 QStandardItem 添加到模型(如 QStandardItemModel )。
示例:
以下是一个示例,展示了如何使用 QStandardItem 来创建一个简单的树形视图应用。
cpp
#include <QApplication>
#include <QTreeView>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QVBoxLayout>
#include <QWidget>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建主窗口
QWidget window;
window.setWindowTitle("QStandardItem Example");
// 创建布局
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建 QStandardItemModel
QStandardItemModel *model = new QStandardItemModel();
model->setHorizontalHeaderLabels({"Name", "Description"});
// 创建根项目
QStandardItem *rootItem = model->invisibleRootItem();
// 创建子项目
QStandardItem *item1 = new QStandardItem("Fruits");
QStandardItem *item1Desc = new QStandardItem("All kinds of fruits");
rootItem->appendRow({item1, item1Desc});
// 添加子项到 Fruits
item1->appendRow(new QStandardItem("Apple"));
item1->appendRow(new QStandardItem("Banana"));
// 创建第二个子项目
QStandardItem *item2 = new QStandardItem("Vegetables");
QStandardItem *item2Desc = new QStandardItem("Various vegetables");
rootItem->appendRow({item2, item2Desc});
// 添加子项到 Vegetables
item2->appendRow(new QStandardItem("Carrot"));
item2->appendRow(new QStandardItem("Tomato"));
// 创建 QTreeView
QTreeView *treeView = new QTreeView();
treeView->setModel(model); // 关联模型
// 将组件添加到布局
layout->addWidget(treeView);
window.setLayout(layout);
window.resize(400, 300);
window.show();
return app.exec();
}
代码解析
- 创建 QApplication:初始化 Qt 应用程序。
- 创建主窗口:使用 QWidget 创建窗口,并设置标题。
- 布局:使用 QVBoxLayout 布局。
- 创建模型:
- 实例化 QStandardItemModel ,设置表头。
- 创建根项目:
- 使用 invisibleRootItem 获取根项目,并向其添加子项目。
- 创建子项目:
- 使用 appendRow 方法将项目及描述添加到根项目中。
- 创建 QTreeView:
- 将模型设置给 QTreeView 以展示树形结构。
- 布局添加:将 QTreeView 添加到布局中。
- 显示窗口:设置窗口大小并显示。
运行结果:

QltemSelectionModel类
QItemSelectionModel 是 Qt 6 中用于管理选中项的类,特别是在与模型(如 QAbstractItemModel )和视图(如 QTableView 、 QTreeView )结合使用时非常有用。它允许你选择、取消选择和查询选中的项。
主要特性
- 多项选择:支持选择多个项。
- 选中状态管理:能够管理项目的选中、取消选中状态。
- 信号和槽:提供信号以响应选中变化,例如 selectionChanged 信号。
- 与视图和模型链接:与任何基于模型的视图(如 QTableView 和 QTreeView )兼容。
示例:
以下是一个简单示例,演示如何使用 QItemSelectionModel 来选择和展示项。
cpp
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include <QVBoxLayout>
#include <QWidget>
#include <QMessageBox>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建主窗口
QWidget window;
window.setWindowTitle("QItemSelectionModel Example");
// 创建布局
QVBoxLayout *layout = new QVBoxLayout(&window);
// 创建 QStandardItemModel
QStandardItemModel *model = new QStandardItemModel(5, 3); // 5行3列
model->setHorizontalHeaderLabels({"Column 1", "Column 2", "Column 3"});
// 填充模型数据
for (int row = 0; row < 5; ++row) {
for (int column = 0; column < 3; ++column) {
model->setItem(row, column, new QStandardItem(QString("Item %1").arg(row * 3 + column + 1)));
}
}
// 创建 QTableView
QTableView *tableView = new QTableView();
tableView->setModel(model); // 关联模型
// 创建 QItemSelectionModel
QItemSelectionModel *selectionModel = new QItemSelectionModel(model);
// 关联选择模型
tableView->setSelectionModel(selectionModel);
// 连接信号以处理选择变化
QObject::connect(selectionModel, &QItemSelectionModel::selectionChanged, [&](const QItemSelection &selected, const QItemSelection &deselected) {
QStringList selectedItems;
for (const QModelIndex &index : selected.indexes()) {
selectedItems << model->item(index.row(), index.column())->text();
}
QMessageBox::information(nullptr, "Selected Items", "You selected:\n" + selectedItems.join("\n"));
});
// 将 QTableView 添加到布局
layout->addWidget(tableView);
window.setLayout(layout);
window.resize(400, 300);
window.show();
return app.exec();
}
代码解析
- 创建 QApplication:初始化 Qt 应用程序。
- 创建主窗口:使用 QWidget 创建窗口,并设置标题。
- 布局:使用 QVBoxLayout 布局。
- 创建模型:
- 实例化 QStandardItemModel ,定义行列数量。
- 使用 setItem 方法填充模型数据。
- 创建 QTableView:
- 将模型设置给 QTableView 以展示数据。
- 创建 QItemSelectionModel:
- 将 QStandardItemModel 传递给 QItemSelectionModel 。
- 设置选择模型:
- 将选择模型关联到 QTableView 。
- 连接信号:
- 连接 selectionChanged 信号,响应选择变化并弹出选择的项。
- 添加 QTableView 到布局:将 QTableView 添加到布局中。
- 显示窗口:设置窗口大小并显示。
运行结果:

自定义代理
在模型/视图结构中,代理的作用可以总结为:
代理的基本功能
- 提供临时编辑器:
- 当视图组件进入编辑状态时,代理创建一个临时编辑器(默认是 QLineEdit )。
- 编辑完成后,将数据提交到数据模型。
自定义编辑器需求
- 根据数据类型定制编辑器:
- 整数列(例如"测深"):
- 使用 QSpinBox 作为编辑器。
- 浮点数列(例如"垂深""方位""总位移"):
- 使用 QDoubleSpinBox 适合浮点数输入。
- 选择列表列(例如"固井质量"):
- 使用 QComboBox 提供选择列表。
- 整数列(例如"测深"):
实现自定义代理
- 创建一个自定义代理类,继承 QStyledItemDelegate 。
- 重写 createEditor() 方法,根据列的数据类型返回适当的编辑器。
- 通过自定义代理,提高数据输入的准确性和效率。
自定义代理的功能
Qt中的QTableView组件默认使用一种代理组件,如果要替换这种默认行为,可以为QTableView的某列或某个单元格设置自定义代理。自定义代理类通常需要从QStyledItemDelegate类继承。
自定义代理类的创建
创建自定义代理类,需要继承自QStyledItemDelegate类。这是创建自定义代理类的基本步骤。
设置自定义代理
设置自定义代理有三种方式:
- setItemDelegate():将自定义代理设置为整个视图组件的代理。
- setItemDelegateForColumn(int column, QAbstractItemDelegate *delegate):为视图组件的某一列设置自定义代理。
- setItemDelegateForRow(int row, QAbstractItemDelegate *delegate):为视图组件的某一行设置自定义代理。
默认代理类
QStyledItemDelegate是视图组件使用的默认代理类。当不设置自定义代理时,视图组件会使用这个默认代理。
目的和意义
- 通过替换默认代理,可以定制QTableView组件的显示和行为,以满足特定的需求。例如,可以自定义单元格的渲染方式、编辑方式等。
QStyledltemDelegate类
QStyledItemDelegate 是 Qt 中用于实现自定义视图组件的代理类,主要用于控制如何绘制和编辑模型中的项。它是 QAbstractItemDelegate 的子类,提供了一些增强的功能。
主要功能:
- 绘制项 :
- paint() 方法用于自定义绘制项的外观,可以设置颜色、字体、对齐方式等。
- 支持使用样式表来调整样式。
- 创建编辑器 :
- createEditor() 方法用于创建适合用户编辑的控件(如 QLineEdit 、 QSpinBox 等)。
- 通过设置自定义编辑器,使数据输入更加符合需求。
- 设置数据 :
- setEditorData() 方法用于将模型中的数据设置到编辑器。
- setModelData() 方法用于将编辑器中的数据保存回模型。
- 更新编辑器 :
- updateEditorGeometry() 方法用于调整编辑器的几何形状,使其适应当前单元格大小。
使用场景:
- 当需要在视图组件(如 QTableView 和 QListView )中使用不同的控件来编辑或显示数据时,可以使用 QStyledItemDelegate 。
- 它适用于希望自定义数据项外观和编辑交互的应用程序。
示例:如何使用 QStyledItemDelegate 创建一个自定义代理,使用 QSpinBox 来编辑整数值。
cpp
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QSpinBox>
// 自定义代理类
class SpinBoxDelegate : public QStyledItemDelegate {
public:
// 创建编辑器
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
QSpinBox *editor = new QSpinBox(parent);
editor->setMinimum(0); // 设置最小值
editor->setMaximum(100); // 设置最大值
return editor;
}
// 设置编辑器的初始数据
void setEditorData(QWidget *editor, const QModelIndex &index) const override {
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(index.data().toInt());
}
// 提交数据到模型
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override {
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
model->setData(index, spinBox->value());
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QTableView tableView;
QStandardItemModel model(5, 2); // 5行2列
// 填充数据
for (int row = 0; row < 5; ++row) {
for (int col = 0; col < 2; ++col) {
model.setItem(row, col, new QStandardItem(QString::number(row * col)));
}
}
tableView.setModel(&model);
// 设置自定义代理
SpinBoxDelegate *delegate = new SpinBoxDelegate();
tableView.setItemDelegateForColumn(0, delegate); // 为第一列设置自定义代理
tableView.show();
return app.exec();
}
**自定义代理类 SpinBoxDelegate **:
- 继承自 QStyledItemDelegate 。
- 实现了三个主要方法:
- createEditor() :返回 QSpinBox 作为编辑器。
- setEditorData() :将模型数据设置到编辑器。
- setModelData() :将编辑器中的数据提交回模型。
主函数:
- 创建 QTableView 和 QStandardItemModel 。
- 填充模型数据。
- 设置自定义代理并展示表格。
运行结果:

QFileSystemModel和QTreeView
QFileSystemModel 类
- 功能 :
- 为本机文件系统提供模型。
- 可访问和操作本机文件系统。
- 主要接口 :
- setRootPath() : 设置根目录。
- 提供获取文件名、目录名、文件大小及详细信息的方法。
- 支持创建、删除和重命名目录。
QTreeView 类
- 功能 :
- 显示树状模型的视图组件。
- 与 QFileSystemModel 结合用于显示文件系统。
- 特性 :
- 点击目录时,可以触发右侧 QListView 和 QTableView 更新显示该目录下的内容。
- 可定义信号来处理目录和文件节点的交互。
应用结构及交互
- 整体界面 :
- 使用 QTreeView 显示文件系统目录树。
- QListView 和 QTableView 显示选中目录的文件和子目录。
- 下方标签显示当前选中节点的信息。
- 交互流程 :
- 在 QTreeView 上选择目录更新右侧视图。
- 点击目录或文件节点更新标签显示详细信息。
QFileSystemModel
QFileSystemModel 是一个 Qt 模型类,用于表示文件系统的层次结构。
它提供文件和目录的信息,可与视图组件(如 QTreeView 或 QListView )结合使用,以便用户浏览文件系统。
主要功能:
- 文件和目录的表示: 自动更新与文件系统的变化同步。
- 支持多种文件属性: 如文件名、大小、类型和最后修改时间。
- 提供功能: 如添加、删除文件和目录。
示例:
cpp
#include <QApplication>
#include <QFileSystemModel>
#include <QTreeView>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QFileSystemModel model;
model.setRootPath(QDir::rootPath()); // 设置根路径
QTreeView treeView;
treeView.setModel(&model);
treeView.setRootIndex(model.index(QDir::rootPath())); // 设置根索引
treeView.setColumnWidth(0, 250); // 设置列宽
treeView.show();
return app.exec();
}
- QStyledItemDelegate 让你可以自定义视图中项的显示和编辑方式。
- QFileSystemModel 提供了一个强大的文件系统模型,可方便地与视图组件交互,帮助用户浏览和管理文件。
运行结果:

QTreeView
QTreeView 是 Qt 中用于显示分层数据的视图组件,常用于呈现树形结构的数据(如文件系统目录、组织结构等)。它支持展开和折叠节点,允许用户以树形方式查看和组织信息。
主要功能:
- 分层结构显示: 适用于显示具有父子关系的数据。
- 支持模型-视图架构: 可与各种模型(如 QStandardItemModel 、 QFileSystemModel 等)结合使用。
- 自定义项的显示与编辑: 提供改变项外观和行为的能力。
示例:如何使用 QTreeView 来显示分层数据。
cpp
#include <QApplication>
#include <QTreeView>
#include <QStandardItemModel>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 创建树形视图
QTreeView treeView;
// 创建模型并添加数据
QStandardItemModel model;
model.setHorizontalHeaderLabels({"Item"});
// 添加根节点
QStandardItem *rootItem = model.invisibleRootItem();
QStandardItem *item1 = new QStandardItem("Item 1");
QStandardItem *item2 = new QStandardItem("Item 2");
rootItem->appendRow(item1);
rootItem->appendRow(item2);
// 添加子节点
QStandardItem *subItem1 = new QStandardItem("Sub Item 1.1");
QStandardItem *subItem2 = new QStandardItem("Sub Item 1.2");
item1->appendRow(subItem1);
item1->appendRow(subItem2);
// 设置模型
treeView.setModel(&model);
// 设置列宽
treeView.setColumnWidth(0, 200);
// 展示树视图
treeView.expandAll(); // 展开所有节点
treeView.show();
return app.exec();
}
代码解析
- 应用程序初始化: 创建 QApplication 实例。
- 创建 QTreeView 实例: 用于显示层次结构的数据。
- **创建 QStandardItemModel **: 用于存储树形数据,通过 setHorizontalHeaderLabels() 设置模型头部。
- 构建树结构: 通过 appendRow() 方法构造父子关系。
- 设置树视图模型: 将模型与树视图关联。
- 展开所有节点: 使用 expandAll() 方法使所有节点展开。
- 运行应用程序: 通过 app.exec() 进入事件循环。
运行结果:
