这是一份讲解模型视图代理最全的文章 开发界面设计必看
Qt的开发过程中,经常会应用到它的模型视图结构,对于初学者来说,马上理解其原理,并且进行基础的应用,还是比较难的。另外,通过网络搜索查看别人发表有关模型视图的介绍,基本上都不能解决个人的一些疑惑。基于此,本文将结合实例来说明模型视图设计的应用,以便能够更加深刻的理解Qt模型视图的设计原理。
任何知识,如果想要能够应用自如,个人觉得首先需要对该知识要有一个整体的认识。所以,首先将对模型视图结构进行总体的说明,然后再结合实例来说明其应用,并且重点介绍代理的两种应用方式,最后再进行总结。
一、模型视图简介
Qt的模型视图与MVC设计模式类似,但是又不相同,MVC设计模式包括模型、视图和控制。模型表示数据,视图表示用户界面,控制定义了用户的操作。它能够有效将数据和显示分离,提高了代码的灵活性。Qt的模型视图同样有这样的效果。但是Qt的模型视图将视图和控制放在一起,以便简化框架。另外,为了能够更好地处理用户输入,Qt的模型视图加入了代理。通过代理能够自定义item的显示和编辑。
Qt的模型视图结构如下图所示,主要包含三个部分,分别为模型、视图和代理。模式与数据源通信,给其他部件提供接口。视图通过ModelIndex从模型中获取信息,代理用来显示和编辑item。
二、模型
模型的抽象基类为QAbstractItemModel, 下图显示了其继承关系。
QAbstractTableModel是表格的抽象基类,QAbstractListMode是列表的抽象基类。QAbstractProxyModel是代理的抽象基类。QDirModel是文件和目录的模型。QSqlQueryModel是有关数据库的模型。
模型的数据可以直接存在模型中,也可以由外部输入,由独立的类管理,还可以存在文件中,甚至是数据库。
模型中角色的功能是,根据不同的角色提供不同的数据。支持以下几种角色。
1、Qt::DisplayRole, 显示文字
2、Qt::DecorationRole,绘制数据
3、Qt::EditRole, 编辑器中的数据
4、Qt::ToolTipRole, 工具提示
5、Qt::StatusTipRole, 状态栏提示
6、Qt::SizeHintRole, 尺寸提示
7、Qt::FontRole, 字体
8、Qt::TextAlignmentRole, 对齐方式
9、Qt::BackgroundRole, 背景画刷
10、Qt::ForegroundRole, 前景画刷
11、Qt::CheckStateRole, 检查框状态
12、Qt::UseRole, 用户自定义数据的起始位置
三、视图
视图的抽象基类为QAbstractItemView, 视图是由五个基本视图类组成,分别是QTreeeView、QHeaderView、QListView、QColumnView和QTableView。为了用户简单方便的使用,还提供了三个模型视图集成的类,分别是QTreeWidget、QListWidget、QTableWidget。对于变动不大,并且简单的需求可以采用这三个类来快速开发。但是对于变动比较大的需求,不建议使用这三个类,因为它们缺乏灵活性。
四、代理
代理的抽象基类为QAbstractItemDelegate, 如果需要改变item的显示或者item的编辑行为,那么可以考虑自定义代理类。
一般自定义代理类是继承QItemDelegate,这可以满足大部分的需求,如果直接继承QAbstractItemDelegate,则需要更多的开发工作量。
如果想要改变item的显示,那么可以通过继承QItemDelegate,然后重载paint来实现。
如果想要改变item的编辑行为,同样的可以继承QItemDelegate,并且需要重载createEditor、setEditorData、setModelData和updateEditorGeometry这个四个接口。
下面的实例将详细介绍代理的这两种应用方式。
五、实例
首先实现模型QAbstractTableModel和表格QtableView的结合显示数据信息的实例。为了代码的清晰度,这里模型直接存储了数据。
JWeaponModel模型的定义如下所示,rowCount返回行数,columnCount返回列数,data实现返回item的数据,headerData则是返回标题信息。flags和setData函数是为了支持代理而添加的,后面会讲解其作用。这里可以暂时不需要太关注。
JWeaponModel模型的实现如下,columnCount默认写死显示三列。date根据角色Qt::DisplayRole来显示不同数据条目的数据。headerData返回水平标题信息。
主程序添加如下代码,QTableView设置模式为JWeaponModel。
编译运行之后的效果如下,显示的数据均来自模型JWeaponModel。
如果想要改变item的编辑行为,支持双击的时候,变成选择框QComboBox,那么考虑使用代理,其定义如下, createEditor创建控件,setEditorData设置控件初始数据,setModelData将编辑数据写入model, 则model需要实现setData(参见JWeaponModel类的实现),这样才能将数据显示到视图。updateEditorGeometry管理控件位置。另外注意,model需要重载flags(参见JWeaponModel类的实现),添加ItemIsEditable属性,否则代理创建的部件显示不出来。
JEditorDelegate对应的实现如下,这里只针对表格第一列进行处理。
主程序进行如下所示的修改,调用QTableView的setItemDelegate来添加代理。
编译运行之后,双击第一列第一行的item, 则出现如下的效果
如果想要改变item的显示,那么也是通过代理的方式来支持,其代理类定义如下,继承QItemDelegate,并重载paint。
对应的实现如下,paint实现了在item中画一个黑色的竖线的功能。
主程序调用QTableView的接口setItemDelegateForColumn添加代理JArrowDelegate,并且设置只对表格的第三列生效。
编译运行效果如下,第三列显示了一条竖线。
六、总结
QT模型视图的原理以及使用说明的讲解就到这里。本文先说明了模型视图的结构,然后再依次说明模型、视图和代理的类层次结构。最后结合具体实例来说明其应用方式,从中可以看出模型提供数据给视图显示,而代理则可以改变数据条目的显示,并通知视图,代理还可以改变数据条目的编辑行为,并通知模型。
想了解更多精彩内容,快来关注软件技术分享