目录
引言
一、MVC思想介绍
1.1 MCV模型概述
1.2 Excel的处理数据
1.3 MVC模式的优势
二、QT中的MVC
1.1 模型(Model)
1. QAbstractItemModel
2. QStringListModel
3. QStandardItemModel
4. QSqlTableModel 和 QSqlQueryModel
5. QAbstractListModel
6. QAbstractProxyModel
7. QStyledItemDelegate
1.2 视图(View)
1. QAbstractItemView
2. QListView
3. QTableView
4. QTreeView
5. 视图类的使用
1.3 委托(Delegate)
1. QItemDelegate类
2. QStyledItemDelegate类
3. 比较
4. 委托类的使用
三、简单的实例
四、结论
引言
在现代软件开发中,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应用程序的代码,提高开发效率和应用程序的质量。