Qt--自定义Model
众所周知,Qt提供了一套Model/View框架供开发者使用,Model用来提供数据, View则用来提供视觉层的显示。实际上这是一套遵循MVC设计模式的GUI框架,因为Qt还提供了默认的Delegate作为Controller来作为控制器。

MVC的好处这里就不多说了,为了开发者使用方便,Qt还提供了基于项(Item)的Model/View实现----QXxxWidget(QTableWidget、QListWidget等),对于一些简单的应用场景,这已经足够了并且使用起来非常方便。这里我们简单介绍下如何使用自定义的数据模型,来满足各种花式的要求。
1. 选择合适的Model继承
1.1 标准数据模型
Qt实现了4类标准数据模型供我们在不同的场景下使用:
- QStringListModel:存储字符串列表。
- QStandardItemModel:存储树状结构的任意数据。
- QFileSystemModel:存储本地文件系统上的文件和目录信息。
- QSqlQueryModel、QSqlRelationalTableModel、QSqlTableModel:存储关系型数据库中的数据。
如果使用情况和上述情况之一比较相似,则可以考虑继承对应的模型类,并重新实现少数虚函数。
1.2 抽象数据模型
抽象数据模型有3类:
- QAbstractItemModel:项模型,这是所有数据模型的基类。
- QAbstractListModel:列表模型,结合QListView使用最合适。
- QAbstractTableModel:表模型,结合QTableView使用最合适。
2. 继承抽象模型
Qt官方提供了完善的文档来帮助开发者来自定义模型类。根据官网,子类化模型需要开发者实现的功能(即需要重新实现的虚函数)按功能来分可以分为三类:
- 项数据处理:这又可以分为三类----只读访问、可编辑、调整大小。
- 导航和下标创建。
- 拖拽和MIME类型处理。
我们只需要按照自己的功能需求来实现其中的一些虚函数。
3. 实现一个自定义模型
这里我们来实现一个自定义模型,并在QTableView中使用它,因此我们选择继承QAbstractTableModel,这样我们需要做的改动最少。但使用QTableModel并不意味着我们的数据结构就是Table状的,例如下面的例子中我们根本不需要内部数据结构。
下面我们要实现这样一个数据模型:
- 内部不存储数据结构。
- 表中的每一个单元获得的数据是整型,并且值为列下标的平方。
- 模型中的数据为只读。
3.1 实现CustomeModel
该模型继承自QAbstractTableModel,作为只读模型,我们只需要实现以下几个虚函数:
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
virtual QVariant data(const QModelIndex &index, int role) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
virtual int rowCount(const QModelIndex &parent) const;
virtual int columnCount(const QModelIndex &parent) const;
data()函数与项数据有关,这里数据有好几种角色(role),最基本的就是Qt::DisplayRole,这里为了实现居中效果,我们还处理了Qt::TextAlignmentRole角色:
QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole) {
return index.column() * index.column();
}
if (role == Qt::TextAlignmentRole) {
return Qt::AlignCenter;
}
return QVariant();
}
headerData()函数提供表头数据,包括两个方向(垂直、水平)的表头。同样,这里的数据也有好几种角色,我们只处理Qt::DisplayRole:
QVariant MyTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Vertical) {
if (role == Qt::DisplayRole) return QVariant("row:" + QString::number(section));
else return QVariant();
}
if (orientation == Qt::Horizontal) {
if (role == Qt::DisplayRole) return QVariant("column:" + QString::number(section));
else return QVariant();
}
}
rowCount()和columnCount()返回数据模父下标(QModelIndex)的行和列数量,这里我们要判别下标是否有效:因为整个表模型的父下标为无效下标,我们返回表模型的行列数量;当下标有效时,我们返回的是父下标指向处的子表的行列:
// if `parent` is invalid, return the whole table row count!
// else return the children row count of the `parent`
int MyTableModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
else
return 10;
}
3.2 运行结果

完整代码见此处。
Qt--自定义Model的更多相关文章
- Qt自定义model
前面我们说了Qt提供的几个预定义model.但是,面对变化万千的需求,那几个model是远远不能满足我们的需要的.另外,对于Qt这种框架来说,model的选择首先要能满足绝大多数功能的需要,这就是说, ...
- Qt 自定义model实现文件系统的文件名排序(重定义sort函数即可。忽然开窍了:其实捕捉点击Header事件,内部重排序,全部刷新显示即可)
前段时间,需要做一个功能是要做文件系统的排序的功能.由于是自己写的model, 自己定义的数据结构.最初的想法只有一个自己去实现文件夹跟文件名的排序算法,不过感觉比较费时间.后来想到的是QFileSy ...
- Qt 自定义model实现文件系统的文件名排序
前段时间,需要做一个功能是要做文件系统的排序的功能.由于是自己写的model, 自己定义的数据结构.最初的想法只有一个自己去实现文件夹跟文件名的排序算法,不过感觉比较费时间.后来想到的是QFileSy ...
- QT内省机制、自定义Model、数据库
本文将介绍自定义Model过程中数据库数据源的获取方法,我使用过以下三种方式获取数据库数据源: 创建 存储对应数据库所有字段的 结构体,将结构体置于容器中返回,然后根据索引值(QModelIndex) ...
- Qt学习之路(45): 自定义model之一
前面我们说了Qt提供的几个预定义model.但是,面对变化万千的需求,那几个model是远远不能满足我们的需要的.另外,对于Qt这种框架来说,model的选择首先要能满足绝大多数功能的需要,这就是说, ...
- Qt之如何自定义model
Qt之如何自定义model https://blog.csdn.net/wei375653972/article/details/86592209
- Undo/Redo for Qt Tree Model
Undo/Redo for Qt Tree Model eryar@163.com Abstract. Qt contains a set of item view classes that use ...
- 浅析在QtWidget中自定义Model
Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系.这种结构带来的功能上的分离给了开发人员更大的弹性来定制数据项的表示,它也提供一个标准的model接 ...
- 浅析在QtWidget中自定义Model(beginInsertRows()和endInsertRows()是空架子,类似于一种信号,用来通知底层)
Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系.这种结构带来的功能上的分离给了开发人员更大的弹性来定制数据项的表示,它也提供一个标准的model接 ...
- PyQt学习随笔:Qt中Model/View中的怎么构造View匹配的Model
老猿Python博文目录 老猿Python博客地址 在<PyQt学习随笔:Qt中Model/View相关的主要类及继承关系>介绍了Model/View架构的主要类,在实际使用时,view相 ...
随机推荐
- HDU5723 Abandoned country (最小生成树+深搜回溯法)
Description An abandoned country has n(n≤100000) villages which are numbered from 1 to n. Since aban ...
- 【mock.js】后端不来过夜半,闲敲mock落灯花 ——南宋·赵师秀
mock的由来[假] 赵师秀:南宋时期的一位前端工程师 诗词背景:在一个梅雨纷纷的夜晚,正值产品上线的紧张时期,书童却带来消息:写后端的李秀才在几个时辰前就赶往临安度假去了, 赵师秀非常生气 ...
- 贡献你的代码,将jar包发布到Maven中央仓库以及常见错误的解决办法
前几天将自己的日志工具发布到了Maven中央仓库中.这个工具本省没有多少技术含量,因为是修改别人的源代码实现的,但是将jar发布到Maven仓库却收获颇丰,因为网上有些教程过时了,在此分享下自己发布j ...
- ida和idr机制分析(盘符分配机制)
# ida和idr机制分析 ida和idr的机制在我个人看来,是内核管理整数资源的一种方法.在内核中,许多地方都用到了该结构(例如class的id,disk的id),更直观的说,硬盘的sda到sdz的 ...
- Linux 组配置文件(/etc/group)
一.概述 Linux 组配置(/etc/group)文件分为4个字段,分别为: 组名.组密码.GID和组成员. 二.示例 用户apple和banana的默认组为fruit. [root@titan ~ ...
- [NOIP2015] 斗地主 大爆搜
考试的时候想了半天,实在是想不到解决的办法,感觉只能暴力..然后暴力也懒得打了,小数据模拟骗30分hhh 然而正解真的是暴力..大爆搜.. 然后我的内心拒绝改这道题(TAT) 不过在wcx大佬的帮助下 ...
- iOS tableview group时头尾视图间隔大小
解决: 一,当使用tableview的格式为group时 1.先设置 tableview.sectionHeaderHeight = 0.00001; tableview.sectionFooterH ...
- Python 3.X安装配置
0x01 安装Python 目前,Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的. 本教程安装的是python-3.6.1-amd64版本. Python官网:https ...
- k-means算法概述
算法过程: 随机选取K个种子点 求所有点到种子点的距离,将点纳入距离最近的种子点群 所有点均被纳入群内后,将种子点移动到种子群中心 重复上述2.3过程,直至种子点没有移动 优缺点: 优点:容易实现 缺 ...
- C语言内存申请与使用
1. 使用malloc申请一块空间,模拟KV存储的一个节点存储数据信息. #include<stdio.h> #include <unistd.h> #include < ...