Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> 使用C++實現QML的TreeView Model (二)

使用C++實現QML的TreeView Model (二)

編輯:關於android開發

使用C++實現QML的TreeView Model (二)


上文已經介紹過二維表模型的實現方式,接著分享層次模型的實現,首先實現一個節點類用於保存樹狀數據模型的節點數據和節點關系:

  1. class TreeNode;

  2. typedef TreeNode* TreeNodePtr;

  3. class TreeNode
  4. {
  5. public:
  6. explicit TreeNode();
  7. TreeNodePtr parent() const;
  8. void setParent(const TreeNodePtr p); //設置父節點,根節點的父節點為NULL
  9. void appendNode(TreeNodePtr node);
  10. void removeNode(int row);
  11. void setData(int role,QVariant value);
  12. QListchilds; //用於保存子節點指針,把childs放到public不好,僅僅是為了方便,不要學。

  13. private:
  14. TreeNodePtr mParent=NULL; //父節點
  15. QHashmRecord; //一個節點可以保存一行數據,哈希表的key是整型,用於保存role,QVariant保存數據

  16. };
TreeNode的實現也是相當簡單:

  1. TreeNodePtr TreeNode::parent() const
  2. {
  3. return mParent;
  4. }

  5. void TreeNode::setParent(const TreeNodePtr p)
  6. {
  7. this->mParent = p;
  8. }

  9. void TreeNode::appendNode(TreeNodePtr node)
  10. {
  11. childs.append(node);
  12. }

  13. void TreeNode::removeNode(int row)
  14. {
  15. childs.removeAt(row);
  16. }


  17. QVariant TreeNode::data(int role)
  18. {
  19. return mRecord[role];
  20. }

  21. void TreeNode::setData(int role, QVariant value)
  22. {
  23. mRecord[role] = value;
  24. }
接下來開始對SqlMenuEntryModel進行手術:

  1. class SqlMenuEntry:public QAbstractItemModel,public QQmlParserStatus
  2. {
  3. Q_OBJECT
  4. public:
  5. explicit SqlMenuEntry(QObject *parent=0);
  6. ~SqlMenuEntry();
  7. enum MenuEntryRoles{idRole=Qt::UserRole+1,nameRole,defaultEntryRole,customEntryRole,iconRole,iconHoverRole};
  8. int rowCount(const QModelIndex &parent=QModelIndex()) const;
  9. int columnCount(const QModelIndex &parent=QModelIndex()) const;
  10. QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const;
  11. QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
  12. QModelIndex parent(const QModelIndex &child) const;
  13. QHashroleNames() const;
  14. private:
  15. QHash mRoleNames;
  16. QList<QHash<int,QVariant>> mRecords; //QList不能保存樹狀數據,干掉
  17. QList mRootEntrys; //用於保存根節點
  18. void _addEntryNode(TreeNodePtr node,TreeNodePtr parent=0); //用於向樹添加節點
  19. };
_addEntryNode的實現如下:

  1. void SqlMenuEntry::_addEntryNode(TreeNodePtr node, TreeNodePtr parent)
  2. {
  3. if(parent == NULL)
  4. {
  5. mRootEntrys.append(node);
  6. }else{
  7. node->setParent(parent);
  8. parent->appendNode(node);
  9. }
  10. }

可以通過如下代碼向模型添加數據:


  1. beginResetModel();

  2. auto node = new TreeNode();
  3. node->setData(nameRole,"parent 1");
  4. node->setData(iconRole,"parenticon1");
  5. _addEntryNode(node); //添加第一個根節點
  6. auto subNode = new TreeNode();
  7. subNode->setData(nameRole,"child1");
  8. _addEntryNode(subNode,node); //添加子節點

  9. endResetModel();
上面的代碼向模型添加了一個根節點parent1和parent1的一個子節點child1,接下來可以對SqlMenuEntryModel進行持續改進,讓TreeView可以順利顯示正確的數據和數據關系。首先,更改int rowCount(const QModelIndex &parent)讓模型可以正確的返回根節點數和子節點行數:

  1. int SqlMenuEntry::rowCount(const QModelIndex &parent) const
  2. {
  3. if(parent.isValid()) //parent不為空,則要獲取的行數是某個節點的子節點行數
  4. {
  5. TreeNodePtr parentNode = (TreeNodePtr)parent.internalPointer(); //節點信息在index時被保存在QModelIndex的internalPointer中
  6. return parentNode->childs.size();
  7. }
  8. return mRootEntrys.size(); //否則返回的是根節點行數

  9. }


實現index接口函數,讓模型可以返回子節點的modelIndex同時將對應的節點指針保存在modelIndex的internalPointer中:

  1. QModelIndex SqlMenuEntry::index(int row, int column, const QModelIndex &parent) const
  2. {
  3. if(!parent.isValid()) //parent為空,返回的是根節點的modelIndex,返回的同時,把節點數據指針(TreeNodePtr)保存在QModelIndex的internalPointer中,以便在其它函數中獲取節點數據
  4. {
  5. if((row >= 0) && (row < mRootEntrys.size()))
  6. {
  7. return createIndex(row,column,mRootEntrys.at(row));
  8. }
  9. }else{
  10. TreeNodePtr parentNode = (TreeNodePtr)parent.internalPointer(); //返回子節點的modelIndex
  11. return createIndex(row,column,parentNode->childs[row]);
  12. }
  13. return QModelIndex();
  14. }
parent(const QModelIndex &child) 用於返回一個節點的父節點索引:

  1. QModelIndex SqlMenuEntry::parent(const QModelIndex &child) const
  2. {
  3. TreeNodePtr node = (TreeNodePtr)child.internalPointer();
  4. if(node->parent() == NULL)
  5. {
  6. return QModelIndex(); //根節點沒有parent
  7. }else{
  8. return createIndex(0,1,node->parent());
  9. }
實現data(constQModelIndex&index,introle) 返回節點中的數據:
  1. QVariant SqlMenuEntry::data(const QModelIndex &index, int role) const
  2. {
  3. TreeNodePtr node = (TreeNodePtr)index.internalPointer();
  4. return node->data(role);
  5. }

經過上面的打造,模型已經可以正常為TreeView提供數據:

  1. TreeView{
  2. anchors.fill: parent
  3. TableViewColumn {
  4. title: "Name"
  5. role: "name"
  6. }

  7. TableViewColumn {
  8. title: "Entry"
  9. role: "icon"
  10. }
  11. model:MenuEntryModel{}
  12. }
繼續干活去了,明天再繼續補充數據添加、刪除和更新的相關經驗。







  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved