众所周知,Qt提供了一套Model/View框架供开发者使用,Model用来提供数据, View则用来提供视觉层的显示。实际上这是一套遵循MVC设计模式的GUI框架,由于Qt还提供了默认的Delegate做为Controller来做为控制器。html
MVC的好处这里就很少说了,为了开发者使用方便,Qt还提供了基于项(Item)的Model/View实现----QXxxWidget(QTableWidget、QListWidget等),对于一些简单的应用场景,这已经足够了而且使用起来很是方便。这里咱们简单介绍下如何使用自定义的数据模型,来知足各类花式的要求。git
Qt实现了4类标准数据模型供咱们在不一样的场景下使用:github
若是使用状况和上述状况之一比较类似,则能够考虑继承对应的模型类,并从新实现少数虚函数。数据库
抽象数据模型有3类:设计模式
Qt官方提供了完善的文档来帮助开发者来自定义模型类。根据官网,子类化模型须要开发者实现的功能(即须要从新实现的虚函数)按功能来分能够分为三类:数据结构
咱们只须要按照本身的功能需求来实现其中的一些虚函数。框架
这里咱们来实现一个自定义模型,并在QTableView中使用它,所以咱们选择继承QAbstractTableModel,这样咱们须要作的改动最少。但使用QTableModel并不意味着咱们的数据结构就是Table状的,例以下面的例子中咱们根本不须要内部数据结构。函数
下面咱们要实现这样一个数据模型:设计
该模型继承自QAbstractTableModel,做为只读模型,咱们只须要实现如下几个虚函数:3d
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; }
完整代码见此处。