Qt自学之路(五)-model/view框架

1、介绍

        为了将数据管理和数据显示职责分开,增加数据管理类及数据显示类的复用性及可扩展性,Qt提供了model/view框架。这个框架原理与MVC设计模式稍有不同。可以认为model/view是一个简化了的MVC设计模式。两者主要区别在于:model/view框架没有提供Controller类。在MVC设计模式中controller类是负责处理用户输入的。而在model/view框架中view类包含了controller类的部分职责。为了增加弹性,model/view框架引入了delegate类,这个类负责数据的显示及数据的编辑功能。有了model/view框架,可以自由组合model类的对象及view类的对象,实现复用。model、view及delegate类的对象之间也是采用信号及槽机制进行通信的。

2、models:负责对数据进行管理。实现通用接口。为delegate,view类对象访问和修改数据提供支持。

(1)所有的model类都是从QAbstractItemModel基类派生出来的。QAbstractItemModel类定义了model的接口。

(2)Qt提供了QAbstractListModel 类,它为底层以为列表方式存储的数据提供了一些默认实现。

(3)Qt提供了QAbstractTableModel 类,它为底层以二维表格方式存储的数据提供了一些默认实现。

(4)Qt还提供了一些内置类,例如:

        1)QStringListModel类:用于管理底层为列表结构的数据。

        2)QStandardItemModel 类:用于管理底层为树形结构的数据,每个数据项可以嵌套一个二维表格。

        3)QFileSystemModel 类:用于提供对本地文件及目录数据的管理。

        4)QSqlQueryModelQSqlTableModel, 及 QSqlRelationalTableModel类用于对以数据库存储的数据进行管理。

(5)model提供了一个统一的接口:无论model管理的数据底层是以什么方式实现的,它对这些实现细节进行了封装并提供了一个统一的抽象模型。在这个抽象模型中,所有数据都是以表格(或嵌套表格)方式进行存储的。

        1)对于底层以列表方式存储的数据,这个抽象模型用一个单列或者单行的表格对这些数据进行表示。如下图所示:

        2)对于底层以二维数组格方式存储的数据,这个抽象模型用一个二维表格来对数据进行表示 。如下图所示:        

        

        3)对于底层以树形结构存储的数据来说,这个抽象模型用嵌套表格的方式进行表示。其中将子树表示为子表格。这个表格被存储于父表格中某个数据项中。如下图所示:

(6)model indexes

        1)model中的每个数据项都对应于一个index。

        2)通过调用QAbstractItemModel::index()成员函数可以根据行号(row),列号(column),父亲index获取目标index

        3)最顶层数据项的index为QModelIndex()。它对应的是一个虚拟的根数据项。

(7)获取model中的数据

        1)通过model->data(index, Qt::DisplayRole)接口函数可以获取model中的数据

        2)每个数据项可能对应多种数据。每个数据对应于一种角色。如下图所示:

 对应于index的数据项有三个数值:

        a)displayRole:字符串数据,对应的是颜色名称。

        b)DecorationRole:rgb数据,对应的是颜色的rgb数值。

        c)ToolTipRole:字符串数据,对应的是数据项的详细描述文字。

3)用户还可以自定义角色类型。

 3、view:实现对数据显示以及对用户的输入提供响应功能。

(1)所有的view类都是从QAbstractItemView基类派生的

(2)view可以直接对数据进行显示,或者通过delegate对象进行显示。

(3)view提供基础的用户响应功能。

(4)每个view对象包含一个QItemSelectionModel 类的对象。view用这个对象来记录用户对数据的选择集。

(5)Qt内置view类:

        1)QListView:将model管理的数据以列表的方式进行显示

         2)QTableView :将model管理的数据以表格的方式进行显示

        3)QTreeView :将model管理的数据以层级列表的方式进行显示             

         4)QHeaderView :用于显示表头。例如:可以为QTreeView类对象可以设置表头对象。如上图所示。QHeaderView类通过调用QAbstractItemModel::headerData() 获取表头数据。

4、Delegate:可以分担view类对数据编辑及对数据显示的功能。

(1)所有delegate类都是从 QAbstractItemDelegate 类派生的

(2)如果delegate负责对数据进行绘制,则delegate类需要重写paint()及sizeHint()虚函数。

(3)当用户对某个数据项进行编辑时,view调用delegate对象的createEditor()函数获取一个合适的控件供用户输入值。当编辑结束时,view负责对编辑控件进行析构。

 (4)当用户输入结束时,view调用delegate对象的setModelData() 函数,对model管理的数据进行修改。

(5)当编辑控件创建时或者被编辑数据项尺寸位置调整时,view会调用delegate对象的updateEditorGeometry()成员函数,调整编辑控件的尺寸及位置。

(6)Qt提供了QStyledItemDelegate类,这个类提供了默认的编辑和显示数据功能。 QListViewQTableView, 及 QTreeView类默认都是使用的这个类的对象作为delegate。

(7)通过调用view对象的setItemDelegate()函数可以修改view对象使用的delegate对象。

5、在view中处理选择

(1)view对象通过QItemSelectionModel 记录被选中的数据项。

(2)selection model包含0或多个选择范围。每个选择范围包含一组连续的选择对象。选择范围由起始索引及终点索引表示(对应于model表格中的一个连续矩形区域,起点为左上角数据项,终点为右下角数据项)。

(3)selection model记录了当前对象的索引。view总是有一个数据项为当前对象。当前对象和对象是否选中状态彼此是独立的。一个对象可以为当前对象但是未被选中。

(4)通过调用QItemSelectionModel::select()成员函数可以对选择集进行更新

        

        其中QItemSelection类的对象表示一个选择范围。QItemSelectionModel::SelectionFlag参数表示更新选择集的方式:

        1)QItemSelectionModel::Select类型:将选择范围中的数据项设置为选择状态

        2)QItemSelectionModel::Deselect类型:将选择范围中的数据项设置为未选择状态

        3)QItemSelectionModel::Toggle类型:将选择范围中的数据项选择状态进行反转

(5)通过调用QItemSelectionModel::setCurrentIndex()成员函数可以更新当前选择项

(6)多个view对象可以共用一个selection model对象,这样做会使多个view中的数据选择状态同步。

6、代理模型

        当需要对model管理的数据进行排序是,可以直接调用model类对象的sort接口。这会直接对model进行修改。有时候多个view可能同时查看同一个model,有些view希望显示排序后的数据,有些view希望显示未排序数据。如果一个view调用了model的sort接口后,所有view显示的数据都是经过排序的了。在这种场景下,就需要使用proxy model。proxy model是在原始model外层进行了一层包裹。view通过proxy model对象间接对底层model进行访问。proxy model并未复制底层model的数据,而是建立了proxy model和原始model索引的一个对应关系。在排序或筛选时仅仅改变索引对应关系,就达到了对数据排序的效果。

        Qt提供了QSortFilterProxyModel 类,这个类实现了排序和筛选功能。如果希望定制排序和筛选逻辑,则需要重写filterAcceptsColumn() ,filterAcceptsRow() ,lessThan() 虚函数即可。

        view使用proxy model的方式如下:

        

         其中,stringListModel为原始model,filterModel为代理model。

        

        

        

        

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值