目录
4. QSqlTableModel 和 QSqlQueryModel
引言
在现代软件开发中,MVC(Model-View-Controller)编程模式因其清晰的结构和高效的开发流程而广受青睐。MVC不仅促进了代码的组织和复用,还提高了应用程序的可扩展性和可维护性。本文将深入探讨MVC模式的思想、原理、组成部分、QT中的MVC以及实现简单示例。
一、MVC思想介绍
1.1 MCV模型概述
MVC是一种将应用程序分为三个核心部分的软件设计模式:模型(Model)、视图(View)和控制器(Controller)。这三个部分各自负责不同的职责,通过明确的接口相互通信,共同协作完成应用程序的功能。
-
模型(Model):负责应用程序的数据和业务逻辑。它代表数据和业务规则,是应用程序的核心。模型接收输入数据,处理业务逻辑,然后返回处理结果。模型与数据库交互,封装了数据的访问逻辑。
-
视图(View):负责数据的展示和用户界面的渲染。视图从模型接收数据,并将其以用户友好的方式呈现给用户。视图不处理业务逻辑,只是展示数据。
-
控制器(Controller):作为模型和视图之间的桥梁,处理用户的输入,并调用模型和视图去完成用户的请求。控制器接收用户的输入(如点击按钮、提交表单等),决定使用哪个模型来处理请求,并选择合适的视图来展示结果。
1.2 Excel的处理数据
通过一个简单的例子来理解什么是MVC架构的思想。
以上是一个Excel表格有学生的成绩,在Excel应用中绘制其树状图和折线图。
当修改Excel表格中的数据,树状图和折线图也会随之更改。
简单来说:
模型(Model):就是Excel表格的数据存储;
视图(View):就是树状图和折线图的视图界面;
控制器(Controller):就是处理输入,并更新模型和视图。
1.3 MVC模式的优势
-
高内聚低耦合:MVC模式通过将应用程序的不同部分分离,降低了它们之间的耦合度,提高了模块的内聚性,使得修改和扩展变得更加容易。
-
易于维护:由于MVC模式将应用程序的不同职责分配给不同的组件,因此当需要修改应用程序时,可以更容易地定位到需要修改的部分,而不会影响到其他部分。
-
可重用性:模型和控制器可以被多个视图重用,提高了代码的重用性。
-
清晰的分工:MVC模式明确了开发人员之间的分工,提高了开发效率。
二、QT中的MVC
在QT中的 控制器 Controller改了个单词 委托 Delegate,就只是简单改了个单词,性质的一样的。
1.1 模型(Model)
在Qt中,MVC(Model-View-Controller)架构的Model部分负责管理和存储数据,以及提供数据访问的接口。Qt框架提供了一系列的Model类来支持这种架构,这些类通常继承自QAbstractItemModel
或它的子类。以下是一些关键的Qt Model类及其特点:
1. QAbstractItemModel
- 概述:这是所有模型类的基类,定义了模型必须实现的基本接口。由于它是一个抽象类,通常不直接使用,而是使用它的子类。
- 功能:提供了模型与视图之间进行数据交互的接口,如
index()
,parent()
,rowCount()
,columnCount()
等方法。
2. QStringListModel
- 概述:这是一个简单的模型类,用于存储和提供QString列表给视图。
- 特点:适用于需要在视图小部件(如
QListView
或QComboBox
)中显示许多字符串的简单情况。 - 使用场景:当应用程序需要从列表中显示一组字符串时,可以使用
QStringListModel
。
3. QStandardItemModel
- 概述:这是一个更通用的模型类,提供了用于存储和管理项目数据的标准方式。
- 特点:支持多维数据(行和列),可以包含不同类型的项(如文本、图标等)。
- 使用场景:适用于需要表格、列表或树形结构显示数据的复杂情况。
4. QSqlTableModel 和 QSqlQueryModel
- 概述:这两个类专门用于与数据库交互,将SQL查询的结果集作为模型数据。
- 特点:
QSqlTableModel
:自动处理多个SQL查询,但通常适用于具有简单表结构的情况。QSqlQueryModel
:允许执行自定义的SQL查询,并将结果集映射为模型数据。
- 使用场景:当应用程序需要从数据库中检索数据并在视图中显示时,可以使用这些类。
5. QAbstractListModel
- 概述:这是一个一维列表模型的基类,提供了处理一维数据列表的接口。
- 特点:比
QStringListModel
更灵活,可以存储任何类型的数据项。 - 使用场景:当需要自定义一维列表模型时,可以继承
QAbstractListModel
。
6. QAbstractProxyModel
- 概述:这是一个代理模型的基类,用于对原始模型的数据进行转换(如排序、过滤等)。
- 子类:包括
QSortFilterProxyModel
(提供排序和过滤功能)和QIdentityProxyModel
(不进行任何修改的代理)。 - 使用场景:当需要对模型数据进行排序、过滤或其他转换时,可以使用代理模型。
7. QStyledItemDelegate
- 概述:虽然
QStyledItemDelegate
不是直接的Model类,但它在MVC架构中扮演了重要角色,用于自定义视图中项的显示和编辑。 - 特点:支持样式表,允许轻松地定制渲染。
- 使用场景:当需要自定义视图中项的渲染方式时,可以继承
QStyledItemDelegate
。
Qt中的MVC Model类提供了丰富的接口和类来支持数据的存储、管理和显示。通过继承和使用这些类,开发者可以轻松地实现复杂的用户界面和数据交互逻辑。在选择Model类时,应根据应用程序的具体需求和数据的特性来决定。
1.2 视图(View)
在Qt中,MVC(Model-View-Controller)架构的View类负责数据的可视化展示,即将模型(Model)中的数据以图形界面的形式呈现给用户。Qt提供了一系列现成的View类,这些类都基于QAbstractItemView
抽象基类,用于实现不同的数据展示方式。以下是对Qt中MVC的View类的详细介绍:
1. QAbstractItemView
- 作用:
QAbstractItemView
是所有视图类的抽象基类,它定义了视图类所需的基本接口和功能。 - 特点:
- 提供了视图的基本属性,如选择模式、滚动模式、拖拽支持等。
- 允许子类通过重写虚函数来自定义视图的行为。
Qt提供了几种具体的View类,以满足不同的数据展示需求:
2. QListView
- 作用:显示一个项目列表,每个项目占据一行。
- 特点:支持单选、多选等选择模式,可以通过设置不同的模式来改变用户的选择行为。
3. QTableView
- 作用:在表格中显示模型中的数据,每个数据项占据一个单元格。
- 特点:支持行选择、列选择或单元格选择,可以自定义表头、列宽、行高等。
- 功能:通过
setAlternatingRowColors
等函数可以设置表格的交替行颜色,提高可读性。
4. QTreeView
- 作用:在分层列表中显示模型数据项,通常用于展示具有层级关系的数据。
- 特点:支持展开/折叠节点,可以根据需要显示或隐藏子项。
5. 视图类的使用
- 设置模型:通过调用视图的
setModel
函数,将模型与视图关联起来。这样,视图就可以从模型中获取数据并进行展示了。 - 自定义视图:如果需要自定义视图的展示方式,可以通过继承
QAbstractItemView
或现有的视图类,并重写相关函数来实现。 - 处理用户交互:视图类提供了丰富的信号和槽机制,用于处理用户的交互操作,如选择项的改变、拖拽操作等。
Qt中的MVC架构中的View类提供了丰富的数据展示方式,通过继承QAbstractItemView
或现有的视图类,并设置模型,可以轻松地实现数据的可视化展示。同时,视图类还提供了丰富的信号和槽机制,用于处理用户的交互操作。
1.3 委托(Delegate)
在Qt的MVC(Model-View-Controller)架构中,虽然Qt官方更偏向于使用Model-View架构(因为Qt没有直接实现一个完整的Controller层,但你可以通过其他方式如信号和槽机制来模拟Controller的行为),Delegate类是一个非常重要的组成部分,它允许你自定义视图(View)中数据的显示和编辑方式。
QStyledItemDelegate类和QItemDelegate类都是Qt框架中用于自定义和控制项视图控件(如QListView、QTableView、QTreeView)中项的显示和编辑的委托类。它们提供了对项的外观和编辑行为的定制能力,但两者之间存在一些关键的区别。
1. QItemDelegate类
- 功能:QItemDelegate是Qt中较早期的委托类,用于处理视图中项的显示和编辑。它继承自QAbstractItemDelegate,并提供了默认的绘制和编辑功能。
- 绘制功能:QItemDelegate使用QStyle进行绘制,这意味着它的绘制风格是基于系统的默认风格。
- 编辑功能:它提供了默认的编辑器(如文本框、复选框等)和编辑行为。
- 自定义性:可以通过重写paint和createEditor等虚函数来自定义项的显示和编辑行为。
- 使用场景:尽管在Qt 4.4之后引入了QStyledItemDelegate,但在一些需要兼容旧版本Qt或特定绘制风格的场景中,QItemDelegate仍然是一个可用的选择。
2. QStyledItemDelegate类
- 功能:QStyledItemDelegate是Qt 4.4引入的,旨在替代QItemDelegate,提供更灵活和现代的项委托。它也是继承自QAbstractItemDelegate,并使用QStyle进行绘制。
- 增强功能:
- 绘制机制:QStyledItemDelegate利用了QStyle的高级功能,可以更好地支持复杂的UI元素和现代风格。
- 统一的风格:它能更好地与Qt的样式系统集成,确保在不同平台和风格下的外观一致性。
- 简化的自定义:提供了一些额外的虚函数(如initStyleOption),使自定义项的显示和编辑更加简单和灵活。
- 使用场景:QStyledItemDelegate是Qt推荐的用于自定义项视图控件中项的显示和编辑的委托类,特别是在需要现代和灵活的绘制风格时。
3. 比较
特性 | QItemDelegate | QStyledItemDelegate |
---|---|---|
引入时间 | 早期 | Qt 4.4 |
绘制机制 | 使用QStyle进行绘制,基于系统默认风格 | 利用QStyle的高级功能,支持更复杂和现代的UI元素 |
自定义性 | 可以通过重写paint和createEditor等虚函数来自定义 | 提供更多虚函数和工具函数,使自定义更加简便和灵活 |
使用场景 | 兼容旧版本Qt或特定绘制风格 | 现代和灵活的绘制风格需求 |
在选择使用QItemDelegate还是QStyledItemDelegate时,应根据项目需求、Qt版本兼容性以及所需的绘制风格等因素进行综合考虑。在大多数情况下,推荐使用QStyledItemDelegate,因为它提供了更强大和灵活的自定义能力,并且能更好地与Qt的样式系统集成。
4. 委托类的使用
-
创建Delegate类:
继承自QStyledItemDelegate
(或QItemDelegate
),然后重写paint
和createEditor
(如果需要编辑)以及setEditorData
、setModelData
等函数。 -
设置Delegate到View:
使用QAbstractItemView
(如QTableView
或QListView
)的setItemDelegate
或setItemDelegateForColumn
/setItemDelegateForRow
方法来将你的Delegate应用到整个视图或特定的列/行上。
三、简单的实例
在qt设计三个视图控件(ListView、TableView、TreeView)来显示本地系统文件结构,当本地系统文件发生改变,视图也随之改变
UI界面:
代码:
#include "widget.h"
#include "ui_widget.h"
#include <QFileSystemModel>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QFileSystemModel *model = new QFileSystemModel(this);
model->setRootPath(QDir::currentPath());
ui->listView->setModel(model);
ui->listView->setRootIndex(model->index(QDir::currentPath()));
ui->treeView->setModel(model);
ui->treeView->setRootIndex(model->index(QDir::currentPath()));
ui->tableView->setModel(model);
ui->tableView->setRootIndex(model->index(QDir::currentPath()));
}
Widget::~Widget()
{
delete ui;
}
运行结果:
当在系统中添加一个测试文件test.txt视图也随之改变:
四、结论
Qt中的MVC架构通过将应用程序分成模型、视图和控制器三个组件,实现了高内聚、低耦合的设计。这种架构使得Qt应用程序更加模块化、灵活和易于维护。通过合理地使用MVC模式,开发者可以更好地组织和管理Qt应用程序的代码,提高开发效率和应用程序的质量。