QAbstractItemModel使用样例与解析
发布日期:2021-06-29 14:42:42
浏览次数:3
分类:技术文章
本文共 5176 字,大约阅读时间需要 17 分钟。
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
参考:qt源码
qstandarditemmodel_p.h qstandarditemmodel.h qstandarditemmodel.cpp qabstractitemmodel.h qabstractitemmodel.cppQAbstractItemModel是一个接口类,使用时需要从它继承下来,实现相关的函数后使用。
不同于QStandardItemModel,使用QAbstractItemModel的话,需要自己构造树形结构数据,并在虚函数中返回对应的值。当然,简单使用的话,也可以快速构造出没有父节点的简单表格结构。
形如根节点下列了几排几列子节点的表格情形。需要继承的类有:
class HistoryModel : public QAbstractItemModel{public: explicit HistoryModel(QObject *parent = 0); // 构造父节点下子节点的索引 virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; // 通过子节点索引获取父节点索引 virtual QModelIndex parent(const QModelIndex &child) const override; // 获取父节点下子节点的行数 virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; // 获取父节点下子节点列数 virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; // 获取节点数据:包括DisplayRole|TextAlignmentRole等 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;};
实现几排几列表格情形的例子:
HistoryModel::HistoryModel(QObject *parent /*= 0*/) : QAbstractItemModel(parent){}QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const{ // 创建普通索引 return createIndex(row, column);}QModelIndex HistoryModel::parent(const QModelIndex &child) const{ // 父节点均为跟节点 return QModelIndex();}int HistoryModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const{ // 根节点下有5行,其它行下没有 if (parent.row() == -1) { return 5; } return 0;}int HistoryModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const{ // 每行有量列 return 2;}QVariant HistoryModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const{ // 节点内容:左对齐,显示行列号 if (role == Qt::TextAlignmentRole) return int(Qt::AlignLeft | Qt::AlignVCenter); else if (role == Qt::DisplayRole) return QString("row=%1,col=%2").arg(index.row()).arg(index.column()); else return QVariant();}
进一步使用,添加树形结构,自己构造树形结构数据:
struct NodeInfo{ QModelIndex parent; // 父节点index QString sData; // 自身数据 QVectorchildNodes; // 子节点 int nRow; int nCol; NodeInfo(QModelIndex parentIdx, QString s, int row, int col):parent(parentIdx), sData(s), nRow(row), nCol(col){}};
生成如下的这种界面:两个level=1节点,每个节点下有一些数据
可以这样来做:
每个节点存储一个NodeInfo信息,这样- 每个节点可以查询子节点数量
- 每个节点可以查询到自身数据
- 可以根据NodeInfo信息(row/col/this)获取到QModeIndex
- 数据构造时,形成NodeInfo的树形层次
- QAbstractItemModel的接口中,index函数中绑定NodeInfo
- QAbstractItemModel的其它接口中,查询NodeInfo并使用
HistoryModel::HistoryModel(QObject *parent /*= 0*/) : QAbstractItemModel(parent){ // 创建root节点 m_pRootNode = new NodeInfo(nullptr, "rootNode", -1, -1); m_receiveInfo = new NodeInfo(m_pRootNode, "ReceiveMessage", 0, 0); m_replyInfo = new NodeInfo(m_pRootNode, "ReplyMessage", 1, 0); m_pRootNode->childNodes.append(m_receiveInfo); m_pRootNode->childNodes.append(m_replyInfo);}QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const{ if (parent.row() == -1 && parent.column() == -1) { // 首层节点绑定关系 if (row < m_pRootNode->childNodes.count()) return createIndex(row, column, m_pRootNode->childNodes[row]); } else { // 其它层节点绑定关系 if (parent.internalPointer() != nullptr) { NodeInfo* pNode = reinterpret_cast(parent.internalPointer()); if (pNode->childNodes.size() > row) { return createIndex(row, column, pNode->childNodes[row]); } } } return QModelIndex();}QModelIndex HistoryModel::parent(const QModelIndex &child) const{ if (child.internalPointer() != nullptr) { NodeInfo* pNode = reinterpret_cast (child.internalPointer()); NodeInfo* pParent = pNode->parent; if (pParent != nullptr) { // 根据父节点信息:row/col/node*获取Index return createIndex(pParent->nRow, pParent->nCol, pParent);; } } return QModelIndex();}int HistoryModel::rowCount(const QModelIndex &parent) const{ if (parent.internalPointer() == nullptr) { // 根节点下的数据行数 return m_pRootNode->childNodes.count(); } else { // 节点下的数据行数 NodeInfo* pNode = reinterpret_cast (parent.internalPointer()); return pNode->childNodes.size(); }}int HistoryModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const{ // 每行有量列 return 1;}QVariant HistoryModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const{ // 节点内容:左对齐,显示行列号 if (role == Qt::TextAlignmentRole) { return int(Qt::AlignLeft | Qt::AlignVCenter); } else if (role == Qt::DisplayRole) { if (index.internalPointer() == 0) { return QString("row=%1,col=%2").arg(index.row()).arg(index.column()); } else { NodeInfo* pNode = reinterpret_cast (index.internalPointer()); return pNode->sData; } } else { return QVariant(); }}
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
转载地址:https://chunyexiyu.blog.csdn.net/article/details/77657624 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月15日 19时10分24秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
二进制补码和原码的记录
2019-04-29
无重叠区间+用最少数量的箭引爆气球
2019-04-29
买卖股票的最佳时机
2019-04-29
AUC粗浅理解笔记记录
2019-04-29
分治法:241. 为运算表达式设计优先级
2019-04-29
广度优先遍历:二进制矩阵中的最短路径
2019-04-29
广度优先遍历:set集合的速度远远比list快:完全平方数
2019-04-29
广度+深度:岛屿的最大面积/岛屿数量
2019-04-29
torch 模型运行时间与forward没对应的可能原因
2019-04-29
130. 被围绕的区域
2019-04-29
欧式距离、余弦相似度和余弦距离
2019-04-29
transform 等效转换(参考源码)
2019-04-29
Docker学习(二):Docker基本操作(控制容器)
2019-04-29
Unity之C#学习笔记(0):环境配置与上手 HelloWorld
2019-04-29
高并发高可用秒杀系统(一)
2019-04-29
php如何将base64数据流文件转换为图片文件?
2019-04-29
JavaScript 的addEventListener() 事件监听详解!
2019-04-29
JavaScript的DOMContentLoaded事件和load的区别?
2019-04-29
PHP+JavaScript实现图片预览上传功能开发!
2019-04-29
JSONView - Chrome插件安装详解!(谷歌浏览器插件)!
2019-04-29