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.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;};

实现几排几列表格情形的例子:

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
childNodes; // 子节点 int nRow; int nCol; NodeInfo(QModelIndex parentIdx, QString s, int row, int col):parent(parentIdx), sData(s), nRow(row), nCol(col){}};

生成如下的这种界面:两个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
(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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:wireshark抓本地包
下一篇:QStandardItemModel的使用

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月15日 19时10分24秒