zoukankan      html  css  js  c++  java
  • Qt QAbstractItemModel使用样例与解析

    参考:qt源码

    1 qstandarditemmodel_p.h
    2 qstandarditemmodel.h
    3 qstandarditemmodel.cpp
    4 qabstractitemmodel.h
    5 qabstractitemmodel.cpp

    QAbstractItemModel是一个接口类,使用时需要从它继承下来,实现相关的函数后使用。
    不同于QStandardItemModel,使用QAbstractItemModel的话,需要自己构造树形结构数据,并在虚函数中返回对应的值。

    当然,简单使用的话,也可以快速构造出没有父节点的简单表格结构。
    形如根节点下列了几排几列子节点的表格情形。

    需要继承的类有:

     1 class HistoryModel : public QAbstractItemModel
     2 {
     3 public:
     4     explicit HistoryModel(QObject *parent = 0);
     5 
     6     // 构造父节点下子节点的索引
     7     virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
     8     // 通过子节点索引获取父节点索引
     9     virtual QModelIndex parent(const QModelIndex &child) const override;
    10     // 获取父节点下子节点的行数
    11     virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    12     // 获取父节点下子节点列数
    13     virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    14     // 获取节点数据:包括DisplayRole|TextAlignmentRole等
    15     virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    16 };

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

     1 HistoryModel::HistoryModel(QObject *parent /*= 0*/)
     2     : QAbstractItemModel(parent)
     3 {
     4 }
     5 
     6 QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const
     7 {
     8     // 创建普通索引
     9     return createIndex(row, column);
    10 }
    11 QModelIndex HistoryModel::parent(const QModelIndex &child) const
    12 {
    13     // 父节点均为跟节点
    14     return QModelIndex();
    15 }
    16 int HistoryModel::rowCount(const QModelIndex &parent /*= QModelIndex()*/) const
    17 {
    18     // 根节点下有5行,其它行下没有
    19     if (parent.row() == -1)
    20     {
    21         return 5;
    22     }
    23     return 0;
    24 }
    25 int HistoryModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const
    26 {
    27     // 每行有量列
    28     return 2;
    29 }
    30 
    31 QVariant HistoryModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
    32 {
    33     // 节点内容:左对齐,显示行列号
    34     if (role == Qt::TextAlignmentRole)
    35         return int(Qt::AlignLeft | Qt::AlignVCenter); 
    36     else if (role == Qt::DisplayRole) 
    37         return QString("row=%1,col=%2").arg(index.row()).arg(index.column());
    38     else
    39         return QVariant();
    40 }

    进一步使用,添加树形结构,自己构造树形结构数据:

    1 struct NodeInfo
    2 {
    3     QModelIndex parent;              // 父节点index
    4     QString sData;                   // 自身数据
    5     QVector<NodeInfo*> childNodes;   // 子节点
    6     int nRow;
    7     int nCol;
    8     NodeInfo(QModelIndex parentIdx, QString s, int row, int col):parent(parentIdx), sData(s), nRow(row), nCol(col){}
    9 };

    生成如下的这种界面:两个level=1节点,每个节点下有一些数据

    可以这样来做:
    每个节点存储一个NodeInfo信息,这样

      1. 每个节点可以查询子节点数量
      2. 每个节点可以查询到自身数据
      3. 可以根据NodeInfo信息(row/col/this)获取到QModeIndex
      4. 数据构造时,形成NodeInfo的树形层次
      5. QAbstractItemModel的接口中,index函数中绑定NodeInfo
      6. QAbstractItemModel的其它接口中,查询NodeInfo并使用
     1 HistoryModel::HistoryModel(QObject *parent /*= 0*/)
     2     : QAbstractItemModel(parent)
     3 {
     4     // 创建root节点
     5     m_pRootNode = new NodeInfo(nullptr, "rootNode", -1, -1);
     6     m_receiveInfo = new NodeInfo(m_pRootNode, "ReceiveMessage", 0, 0);
     7     m_replyInfo = new NodeInfo(m_pRootNode, "ReplyMessage", 1, 0);
     8     m_pRootNode->childNodes.append(m_receiveInfo);
     9     m_pRootNode->childNodes.append(m_replyInfo);
    10 }
    11 
    12 QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent /*= QModelIndex()*/) const
    13 {
    14     if (parent.row() == -1 && parent.column() == -1)
    15     {
    16         // 首层节点绑定关系
    17         if (row < m_pRootNode->childNodes.count())
    18             return createIndex(row, column, m_pRootNode->childNodes[row]);
    19     }
    20     else
    21     {
    22         // 其它层节点绑定关系
    23         if (parent.internalPointer() != nullptr)
    24         {
    25             NodeInfo* pNode = reinterpret_cast<NodeInfo*>(parent.internalPointer());
    26             if (pNode->childNodes.size() > row)
    27             {
    28                 return createIndex(row, column, pNode->childNodes[row]);
    29             } 
    30         }
    31     }
    32     return QModelIndex();
    33 }
    34 
    35 QModelIndex HistoryModel::parent(const QModelIndex &child) const
    36 {
    37     if (child.internalPointer() != nullptr)
    38     {
    39         NodeInfo* pNode = reinterpret_cast<NodeInfo*>(child.internalPointer());
    40         NodeInfo* pParent = pNode->parent;
    41         if (pParent != nullptr)
    42         {
    43             // 根据父节点信息:row/col/node*获取Index
    44             return createIndex(pParent->nRow, pParent->nCol, pParent);;
    45         }
    46     }
    47     return QModelIndex();
    48 }
    49 int HistoryModel::rowCount(const QModelIndex &parent) const
    50 {
    51     if (parent.internalPointer() == nullptr)
    52     {
    53         // 根节点下的数据行数
    54         return m_pRootNode->childNodes.count();
    55     }
    56     else
    57     {
    58         // 节点下的数据行数
    59         NodeInfo* pNode = reinterpret_cast<NodeInfo*>(parent.internalPointer());
    60         return pNode->childNodes.size();
    61     }
    62 }
    63 int HistoryModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const
    64 {
    65     // 每行有量列
    66     return 1;
    67 }
    68 
    69 QVariant HistoryModel::data(const QModelIndex &index, int role /*= Qt::DisplayRole*/) const
    70 {
    71     // 节点内容:左对齐,显示行列号
    72     if (role == Qt::TextAlignmentRole)
    73     {
    74         return int(Qt::AlignLeft | Qt::AlignVCenter); 
    75     }
    76     else if (role == Qt::DisplayRole) 
    77     {
    78         if (index.internalPointer() == 0)
    79         {
    80             return QString("row=%1,col=%2").arg(index.row()).arg(index.column());
    81         }
    82         else
    83         {
    84             NodeInfo* pNode = reinterpret_cast<NodeInfo*>(index.internalPointer());
    85             return pNode->sData;
    86         }
    87     }
    88     else
    89     {
    90         return QVariant();
    91     }
    92 }
  • 相关阅读:
    剑指Offer——翻转单词顺序列
    剑指Offer——左旋转字符串
    剑指Offer——和为S的两个数字
    剑指Offer——和为S的连续正数序列
    剑指Offer——数组中只出现一次的数字
    log4cxx入门第一篇--一个小例子
    gsoap写一个c++ webservice
    Protocol Buffer技术详解(数据编码)
    Protocol Buffer技术详解(Java实例)
    Protocol Buffer技术详解(C++实例)
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/13516386.html
Copyright © 2011-2022 走看看