Model/View框架总体架构 分类: QT学习实践 2015-05-11 22:05 34人阅读 评论(0) 收藏
2015-05-11 22:05
519 查看
原文:http://book.2cto.com/201209/4214.html
Model/View框架中,所有模型类具有共同的抽象基类QAbstractItemModel,所有视图类具有共同的抽象基类QAbstractItemView,所有委托类具有共同的抽象基类QabstractItem Delegate。这些类之间的协作关系如图13-4所示。
Model/View框架涉及的类如图13-5所示。初看起来这个框架非常复杂,但是由于所有的模型类、视图类、委托类都遵循上述协作关系,我们其实只需关注QAbstractItemModel的各个子类的区别、QAbstractItemView的各个子类的区别以及QAbstractItemDelegate的各个子类的区别。
(1)模型类。作为所有模型类的抽象基类,QAbstractItemModel定义了模型访问接口。这个接口是一组纯虚函数,负责访问数据集中的数据项。该类将数据集看作一棵树,但是该类并没有定义任何数据成员来存放数据集。类似地,除了具有灰色背景的类Qstandard ItemModel外,其他模型类也都如此。由于QAbstractItemModel是一个抽象基类,我们并不能直接定义该类的对象。使用模型类的一个简单做法是了解QAbstractItemModel各个派生类的功能,寻找一个与应用程序数据集特征最接近的派生类,定义该类的对象或者派生该类的子类。如果QAbstractItemModel的所有派生类都无法满足我们的要求(比如性能方面的),我们才需要直接派生QAbstractItemModel的子类,但这需要实现模型访问接口中的几个纯虚函数,编程工作量较大。
QAbstractListModel负责处理具有列表结构的数据集。它已经实现了部分模型访问接口,我们只需派生该类的子类,实现模型访问接口中的其他虚函数,因而比直接派生QAbstractItemModel的子类要简单。如果应用程序只是企图显示、编辑一些字符串,可以使用QAbstractListModel的子类QStringListModel。程序员所需做的只是将这些字符串写入一个QStringList对象中,然后将这个对象传递给一个QStringListModel对象。后者实现了整个模型访问接口,因而程序员不需要重载它的任何成员函数。
QAbstractTableModel负责处理具有表格结构的数据集。它已经实现了部分模型访问接口,我们只需派生该类的子类,实现模型访问接口中的其他虚函数。它的派生类QsqlQueryModel,QsqlTableModel,QSqlRelationalTableModel和关系型数据库相关,限于篇幅,本书不予讨论。
QStandardItemModel负责处理具有树状层次结构的数据集。当然,由于列表、表格也可以被看作特殊的树,该类实际上也可以处理具有列表、表格结构的数据集。和前面几个模型类不同,该类在其内部定义了一个数据结构,用来存放树状结构的数据集。它使用类QStandardItem表示一个树节点,QStandardItem定义了一些数据成员,用来存放数据集的数据。另外,它还定义了一些指针,每个指针指向另外一个QStandardItem对象,形成当前节点的子节点。通过这种方式,QStandardItemModel可以存储具有任意多层的树状数据集。
QFileSystemModel专门负责处理本地文件系统。它实现了整个模型访问接口,其他视图类通过该类可以立即显示本地文件系统。
和前面的模型类都不同,QAbstractProxyModel并不直接处理数据集,它对其他模型中的数据项进行一些处理,再将处理结果呈现给框架中的其他对象。该类的子类QsortFilterProxy Model能够做排序、筛选处理。
(2)视图类。作为所有视图类的抽象基类,QAbstractItemView负责绘制总体外观并处理用户的交互命令。由于它是一个抽象类,我们不能直接定义该类的对象,而是应该在该类的派生类中,选择一个和数据集拓扑结构相似的类,定义其对象来显示数据集。QListView适合显示具有列表结构的数据集,QTableView适合显示表格结构的数据集,QTreeView以及QColumnView适合显示树状结构的数据集。QHeaderView仅被用来显示标头部分,与数据项无关。
以上几个视图类实现普通视图的功能,在它们的内部没有定义任何模型对象。使用这些视图类时,程序员必须自行构造模型对象。为了方便对Model/View框架的使用,Qt还提供了一组便利视图类。这些类在其内部定义了模型对象,并定义了一组简洁、易用的成员函数来操作模型对象中的数据项。其中,QListWidget存储并显示一个列表,QTableWidget存储并显示一个表格,QTreeWidget存储并显示一棵树。在图中这些类的背景被显示为灰色,表示它们包含模型对象。这些视图类分别使用类QlistWidgetItem,QTableWidgetItem以及QTreeWidgetItem表示模型对象中的数据项。
对于QListWidget表示的列表或者QTableWidget表示的表格,依据其行数、列数即可遍历整个数据集。对于QTreeWidget表示的树状数据集,遍历所有树节点并非易事。为此,Model/View框架提供了迭代器QTreeWidgetItemIterator,对QTreeWidget表示的树进行前序遍历。
3)委托类。抽象基类QAbstractItemDelegate及其子类负责视图中每个数据项的绘制与编辑。视图类的内部定义了一个指针,指向一个委托对象。当视图需要绘制每个数据项时,会将该数据项的屏幕位置等信息传递给委托对象进行绘制。
QAbstractItemDelegate的子类QItemDelegate总是以一种默认的风格绘制数据项,而它的另外一个子类QStyledItemDelegate使用应用程序当前的界面风格进行绘制,使得整个界面具有协调一致的风格,因而我们应该尽可能地使用后者。当用户需要编辑某个数据项时,委托对象会将目标数据项的类型传递给类QItemEditorFactory,后者负责创建一个能够编辑该类型的编辑器控件,对目标数据项进行编辑。编辑完毕后,委托对象调用模型访问接口,将编辑结果写回模型。
(4)索引。在视图类或者委托类看来,模型类中的数据集总是一棵树,该树可能具有多层树节点。由于模型的访问者对数据集的存放方式一无所知,为了表示要访问哪个节点,访问者会通知模型类目标节点的父节点,以及在这个父节点所包含的所有子节点中,目标节点所在的行号、列号。模型类收到这些信息后,在数据集中找到目标节点,创建一个QModelIndex对象,逻辑上指向这个节点,这个QModelIndex对象就被称为目标节点的索引。模型的访问者此后就可以使用这个索引来访问目标节点,提高了访问效率。另外,QModelIndex内部还定义了一个指针,指向它所属的模型对象。这样,给定一个索引,不再需要任何其他信息,就可以唯一确定一个模型对象中的一个数据项。
当数据集发生变化时,比如部分数据项被删除或者有新的数据项加入,QModelIndex表示的索引可能失效,也就是不再指向原先所指的数据项。而QPersistentModelIndex所表示的索引却总是指向某一个数据项,不会随着数据集的变化而失效,除非它所指的数据项被删除。
(5)选择。视图类允许用户选择一些数据项。在最复杂情况下,用户可以选择多个父节点所包含的多个子节点。以从上到下、从左到右的阅读顺序,每个父节点下被选的多个子节点可能是不连续的。我们将连续的被选子节点形成的集合称为“选择块”。一个QItemSelectionRange对象记录一个选择块的范围信息,它使用数据成员tl(top-left)表示选择块左上角数据项的索引,使用数据成员br(bottom-right)表示选择块右下脚数据项的索引。一个QItemSelection对象包含多个QItemSelectionRange对象,表示多个选择块的信息。
视图类使用QItemSelectionModel记录选择信息,该类的数据成员currentSelection所指的QItemSelection对象表示用户最近一次所做的选择,而数据成员ranges所指的QItemSelection对象表示最近一次之前所选的选择块。
Model/View框架中,所有模型类具有共同的抽象基类QAbstractItemModel,所有视图类具有共同的抽象基类QAbstractItemView,所有委托类具有共同的抽象基类QabstractItem Delegate。这些类之间的协作关系如图13-4所示。
Model/View框架涉及的类如图13-5所示。初看起来这个框架非常复杂,但是由于所有的模型类、视图类、委托类都遵循上述协作关系,我们其实只需关注QAbstractItemModel的各个子类的区别、QAbstractItemView的各个子类的区别以及QAbstractItemDelegate的各个子类的区别。
(1)模型类。作为所有模型类的抽象基类,QAbstractItemModel定义了模型访问接口。这个接口是一组纯虚函数,负责访问数据集中的数据项。该类将数据集看作一棵树,但是该类并没有定义任何数据成员来存放数据集。类似地,除了具有灰色背景的类Qstandard ItemModel外,其他模型类也都如此。由于QAbstractItemModel是一个抽象基类,我们并不能直接定义该类的对象。使用模型类的一个简单做法是了解QAbstractItemModel各个派生类的功能,寻找一个与应用程序数据集特征最接近的派生类,定义该类的对象或者派生该类的子类。如果QAbstractItemModel的所有派生类都无法满足我们的要求(比如性能方面的),我们才需要直接派生QAbstractItemModel的子类,但这需要实现模型访问接口中的几个纯虚函数,编程工作量较大。
QAbstractListModel负责处理具有列表结构的数据集。它已经实现了部分模型访问接口,我们只需派生该类的子类,实现模型访问接口中的其他虚函数,因而比直接派生QAbstractItemModel的子类要简单。如果应用程序只是企图显示、编辑一些字符串,可以使用QAbstractListModel的子类QStringListModel。程序员所需做的只是将这些字符串写入一个QStringList对象中,然后将这个对象传递给一个QStringListModel对象。后者实现了整个模型访问接口,因而程序员不需要重载它的任何成员函数。
QAbstractTableModel负责处理具有表格结构的数据集。它已经实现了部分模型访问接口,我们只需派生该类的子类,实现模型访问接口中的其他虚函数。它的派生类QsqlQueryModel,QsqlTableModel,QSqlRelationalTableModel和关系型数据库相关,限于篇幅,本书不予讨论。
QStandardItemModel负责处理具有树状层次结构的数据集。当然,由于列表、表格也可以被看作特殊的树,该类实际上也可以处理具有列表、表格结构的数据集。和前面几个模型类不同,该类在其内部定义了一个数据结构,用来存放树状结构的数据集。它使用类QStandardItem表示一个树节点,QStandardItem定义了一些数据成员,用来存放数据集的数据。另外,它还定义了一些指针,每个指针指向另外一个QStandardItem对象,形成当前节点的子节点。通过这种方式,QStandardItemModel可以存储具有任意多层的树状数据集。
QFileSystemModel专门负责处理本地文件系统。它实现了整个模型访问接口,其他视图类通过该类可以立即显示本地文件系统。
和前面的模型类都不同,QAbstractProxyModel并不直接处理数据集,它对其他模型中的数据项进行一些处理,再将处理结果呈现给框架中的其他对象。该类的子类QsortFilterProxy Model能够做排序、筛选处理。
(2)视图类。作为所有视图类的抽象基类,QAbstractItemView负责绘制总体外观并处理用户的交互命令。由于它是一个抽象类,我们不能直接定义该类的对象,而是应该在该类的派生类中,选择一个和数据集拓扑结构相似的类,定义其对象来显示数据集。QListView适合显示具有列表结构的数据集,QTableView适合显示表格结构的数据集,QTreeView以及QColumnView适合显示树状结构的数据集。QHeaderView仅被用来显示标头部分,与数据项无关。
以上几个视图类实现普通视图的功能,在它们的内部没有定义任何模型对象。使用这些视图类时,程序员必须自行构造模型对象。为了方便对Model/View框架的使用,Qt还提供了一组便利视图类。这些类在其内部定义了模型对象,并定义了一组简洁、易用的成员函数来操作模型对象中的数据项。其中,QListWidget存储并显示一个列表,QTableWidget存储并显示一个表格,QTreeWidget存储并显示一棵树。在图中这些类的背景被显示为灰色,表示它们包含模型对象。这些视图类分别使用类QlistWidgetItem,QTableWidgetItem以及QTreeWidgetItem表示模型对象中的数据项。
对于QListWidget表示的列表或者QTableWidget表示的表格,依据其行数、列数即可遍历整个数据集。对于QTreeWidget表示的树状数据集,遍历所有树节点并非易事。为此,Model/View框架提供了迭代器QTreeWidgetItemIterator,对QTreeWidget表示的树进行前序遍历。
3)委托类。抽象基类QAbstractItemDelegate及其子类负责视图中每个数据项的绘制与编辑。视图类的内部定义了一个指针,指向一个委托对象。当视图需要绘制每个数据项时,会将该数据项的屏幕位置等信息传递给委托对象进行绘制。
QAbstractItemDelegate的子类QItemDelegate总是以一种默认的风格绘制数据项,而它的另外一个子类QStyledItemDelegate使用应用程序当前的界面风格进行绘制,使得整个界面具有协调一致的风格,因而我们应该尽可能地使用后者。当用户需要编辑某个数据项时,委托对象会将目标数据项的类型传递给类QItemEditorFactory,后者负责创建一个能够编辑该类型的编辑器控件,对目标数据项进行编辑。编辑完毕后,委托对象调用模型访问接口,将编辑结果写回模型。
(4)索引。在视图类或者委托类看来,模型类中的数据集总是一棵树,该树可能具有多层树节点。由于模型的访问者对数据集的存放方式一无所知,为了表示要访问哪个节点,访问者会通知模型类目标节点的父节点,以及在这个父节点所包含的所有子节点中,目标节点所在的行号、列号。模型类收到这些信息后,在数据集中找到目标节点,创建一个QModelIndex对象,逻辑上指向这个节点,这个QModelIndex对象就被称为目标节点的索引。模型的访问者此后就可以使用这个索引来访问目标节点,提高了访问效率。另外,QModelIndex内部还定义了一个指针,指向它所属的模型对象。这样,给定一个索引,不再需要任何其他信息,就可以唯一确定一个模型对象中的一个数据项。
当数据集发生变化时,比如部分数据项被删除或者有新的数据项加入,QModelIndex表示的索引可能失效,也就是不再指向原先所指的数据项。而QPersistentModelIndex所表示的索引却总是指向某一个数据项,不会随着数据集的变化而失效,除非它所指的数据项被删除。
(5)选择。视图类允许用户选择一些数据项。在最复杂情况下,用户可以选择多个父节点所包含的多个子节点。以从上到下、从左到右的阅读顺序,每个父节点下被选的多个子节点可能是不连续的。我们将连续的被选子节点形成的集合称为“选择块”。一个QItemSelectionRange对象记录一个选择块的范围信息,它使用数据成员tl(top-left)表示选择块左上角数据项的索引,使用数据成员br(bottom-right)表示选择块右下脚数据项的索引。一个QItemSelection对象包含多个QItemSelectionRange对象,表示多个选择块的信息。
视图类使用QItemSelectionModel记录选择信息,该类的数据成员currentSelection所指的QItemSelection对象表示用户最近一次所做的选择,而数据成员ranges所指的QItemSelection对象表示最近一次之前所选的选择块。
相关文章推荐
- QSqlQuery类参考 分类: QT学习实践 2015-05-11 08:45 31人阅读 评论(0) 收藏
- Qt简介以及如何配置Qt使用VS2010进行开发 分类: QT学习实践 2015-05-05 16:02 34人阅读 评论(0) 收藏
- Qt 2D绘图 分类: QT学习实践 2015-05-03 09:58 27人阅读 评论(0) 收藏
- Qt学习笔记(一) 分类: QT学习实践 2015-05-03 20:51 43人阅读 评论(0) 收藏
- QT与QT Creator的独立安装与配置 分类: QT学习实践 2015-04-29 23:20 40人阅读 评论(0) 收藏
- This application failed to start because it could not find or load the Qt platform plugin “... 分类: QT学习实践 2015-05-17 18:21 44人阅读 评论(0) 收藏
- Ubuntu 13.04下构建Qt5开发环境 分类: QT学习实践 2015-04-30 10:12 35人阅读 评论(0) 收藏
- 用Qt还是MFC 分类: QT学习实践 2015-05-07 23:17 30人阅读 评论(0) 收藏
- 和大彪一起来学习-SpringMvc之第一回(框架了解和第一个SpringMvc程序) 分类: SpringMvc 2015-01-14 21:08 636人阅读 评论(0) 收藏
- 【ASP.NET开发】ASP.NET(MVC)三层架构知识的学习总结 分类: ASP.NET 2012-09-27 17:09 1985人阅读 评论(1) 收藏
- 和大彪一起来学习-SpringMvc之第一回(框架了解和第一个SpringMvc程序) 分类: SpringMvc 2015-01-14 21:08 635人阅读 评论(0) 收藏
- qt 在linux环境下的搭建 (自己整理) 分类: 嵌入式开发学习 2011-04-29 20:54 6033人阅读 评论(0) 收藏
- Lucene学习总结之二:Lucene的总体架构 2014-06-25 14:12 622人阅读 评论(0) 收藏
- 静态方法 分类: python基础学习 2014-04-05 19:34 228人阅读 评论(0) 收藏
- Android 快速开发系列 ORMLite 框架最佳实践 标签: AndroidORMLite 2014-09-07 23:47 62916人阅读 评论(36) 收藏 举报 分类: 【Androi
- 系统学习深度学习(七)--主流深度学习开源框架对比 2017-01-23 11:05 2292人阅读 评论(0) 收藏 举报 分类: 深度学习(30) 目录(?)[+] 转自:http://b
- python random模块 分类: python python Module python基础学习 2013-06-26 12:06 383人阅读 评论(0) 收藏
- ubuntu 为rabbitmq安装web插件管理界面(为了远程查看rabbitmq) 分类: 软件插件学习 2014-03-05 13:42 1411人阅读 评论(0) 收藏
- TextView之二:常用属性 分类: H1_ANDROID 2013-10-30 12:43 3203人阅读 评论(0) 收藏
- gzip 压缩格式的网站处理方法---sina.com 分类: python python基础学习 2013-07-16 17:40 362人阅读 评论(0) 收藏