参考:qt源码
qstandarditemmodel_p.h
qstandarditemmodel.h
qstandarditemmodel.cpp
qabstractitemmodel.h
qabstractitemmodel.cpp

QAbstractItemModel是一个接口类,使用时需要从它继承下来,实现相关的函数后使用。
不同于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;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
实现几排几列表格情形的例子:

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; // 自身数据
QVector<NodeInfo*> childNodes; // 子节点
NodeInfo(QModelIndex parentIdx, QString s):parent(parentIdx), sData(s){}
};
1
2
3
4
5
6
7
生成如下的这种界面:两个level=1节点,每个节点下有一些数据

可以这样来做:
每个节点存储一个NodeInfo信息,这样
1. 每个节点可以查询子节点数量
2. 每个节点可以查询到自身数据
3. 可以根据NodeInfo信息(row/col/this)获取到QModeIndex
4. 数据构造时,形成NodeInfo的树形层次
5. QAbstractItemModel的接口中,index函数中绑定NodeInfo
6. 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<NodeInfo*>(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<NodeInfo*>(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<NodeInfo*>(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<NodeInfo*>(index.internalPointer());
return pNode->sData;
}
}
else
{
return QVariant();
}
}
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
---------------------
作者:春夜喜雨
来源:CSDN
原文:https://blog.csdn.net/chunyexiyu/article/details/77657624
版权声明:本文为博主原创文章,转载请附上博文链接!

void wokr()
{
QModelIndex index = model.getIndex();
...
...
return;
// 局部变量,函数退出时自动回收。
} std::string func()
{
return "";
}
你需要管返回值谁释放嘛? 奇怪的问题 std::string* func()
{
return new std::string("");
}
但是这个你就要关心了

最新文章

  1. RunLoop 总结:RunLoop的应用场景(二)
  2. Android学习简单总结
  3. google地图引入网页
  4. session 和 cookie 的区别和联系
  5. PHP中对数据库操作的封装
  6. CMSIS RTOS -- embOS segger
  7. 分享一道我认为非常有思考价值JavaScript题目
  8. Android文件下载(实现断点续传)
  9. [面经] 南京SAP面试(上)
  10. 每天记录一点:NetCore获得配置文件 appsettings.json
  11. node上传文件并在网页中展示
  12. tp5命令行
  13. 通过代码启动appium服务
  14. 【Android】setHapticFeedbackEnabled 设置
  15. 构建oracle12c的Docker镜像
  16. JavaScript使用注意事项
  17. 如何删除jsPlumb连接
  18. 关于在VS2008和VS2010中禁用及卸载Visual Assist X的方法研究——转载
  19. mybatis插入数据并获取主键值
  20. Atcoder:AGC004F Namori

热门文章

  1. 解决oracle服务占用内存过高的问题
  2. Javascript中数组查重的方法总结大全
  3. Resend a Request by fiddler
  4. layer快速点击会触发多次回调
  5. 漫谈Objective-C在语法上的改进
  6. Servlet 的三种跳转方式
  7. 003-多线程-JUC集合-Set-CopyOnWriteArrayList
  8. mysql大数据量下优化
  9. unity 读取灰度图生成三维地形并贴图卫星影像
  10. Flutter 的一些小技巧