Smalltalk
的设计模式,通常用于构建用户界面。Qt
库提供了许多预定义的模型和视图类,如QStandardItemModel、QListView、QTableView等,开发人员可以根据自己的需求选择合适的类来建立模型和视图。同时,开发人员也可以自定义模型和视图类来适应特定的应用场景。模型/视图
,如下所示:
数据本身并不一定存储在模型中,可以储存在一个数据结构,或者一个文件,一个数据库,或者其他组件中,都是有可能的。
如:一个数据类型,QStringList
QStringList sl;
sl << QString("1") << QString("2") << QString("3") << QString("4") << QString("5") << QString("6");
如果视图是列表,那sl
可以显示为6行1列;如果视图为表格,则根据表格行列,可显示为对应的视图;但数据还是那个数据,不变。
一般来说,模型/视图架构可以分为3类:模型、视图和委托。
在Qt中,每个类都有一个抽象基类来定义,提供了一些通用接口和一些功能的默认实现;抽象类呢,就允许编写自定义的组件。
其中,这三者之间的交互是通过信号和槽来实现:
查看其手册,发现所有模型类的基类都是QAbstractItemModel
类。
该类提供了一些接口,用于让视图和委托访问数据。
QAbstractItemModel
提供了一个灵活的数据接口,可以处理以表格、列表和树形形式表示数据的视图。
但是,当为列表和类似表格的数据结构实现新模型时,可以继承至QAbstractListModel
和QAbstractTableModel
类,因为它们提供了列表和表格等常用的一些函数。每个类都可以被子类化,以提供支持特殊类型的列表和表格的模型。
Qt提供了一些现成的模型,可以用来处理数据项:
如果这些标准模型不满足需求,可以子类化 QAbstractItemModel、QAbstractListModel 或 QAbstractTableModel 来创建自定义模型。
Qt提供了几种不同类型的视图:
这些类都是基于QAbstractItemView抽象基类。这些类可以直接使用,也可以通过子类化来提供自定义视图。
QAbstractItemDelegate
是模型/视图框架中委托的抽象基类。QStyledItemDelegate
提供了默认的委托实现,并且被Qt的标准视图用作默认的委托。但是,QStyledItemDelegate
和QItemDelegate
是独立存在的,只能选泽其中一种为视图中的项目绘制和提供编辑器。它们之间的区别在于QStyledItemDelegate
使用当前的样式来绘制其项目。因此,当实现自定义委托或使用Qt样式表时,建议将QStyledItemDelegate
作为基类使用。
以上说了MVC的作用及模型、视图、委托的介绍,下面是一个示例进行简单说明。
QFileSystemModel
类为本地文件系统提供了一个数据模型,本身不包含任何的数据,它代表了本地文件系统中的文件和目录。
该类提供对本地文件系统的访问,提供了重命名和删除文件和目录的功能,以及创建新目录的功能。在最简单的情况下,它可以与适当的显示部件一起用作浏览器或筛选器的一部分。
QFileSystemModel
可以使用QAbstractItemModel
提供的标准接口访问,但它还提供了一些特定于目录模型的方便函数。fileInfo()、isDir()、fileName()和filePath()函数提供了与模型中项目相关的底层文件和目录的信息。可以使用mkdir()和rmdir()函数创建和删除目录。
QFileSystemModel
类可以和QListView
或QTreeView
一起用来显示内容。
#include <QDir>
#include <QTreeView>
#include <QListView>
#include <QFileSystemModel>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QListView* pLV = new QListView();
QTreeView* pTW = new QTreeView(this);
QFileSystemModel* pModel = new QFileSystemModel(this);
pTW->setModel(pModel);
pModel->setRootPath(QDir::currentPath());
pTW->setRootIndex(pModel->index(QDir::currentPath()));
setCentralWidget(pTW);
pLV->setModel(pModel);
pLV->setRootIndex(pModel->index(QDir::currentPath()));
pLV->show();
}
同一个模型,根据视图不同,显示不同的方式;由此可看到模型/视图的好处。
如果是大量数据显示,或者想有更高的控制权,建议使用View/Model。