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函数是为了支持代理而添加的,后面会讲解其作用。这里可以暂时不需要太