1、TreeViewItem.h

#pragma once
#include <QList>
class TreeViewItem
 {
 public:    TreeViewItem(const QList<QVariant>& data, TreeViewItem* parent = NULL);
    ~TreeViewItem();
    void appendChild(TreeViewItem* child);
    void deleteAllChild();
    TreeViewItem* child(int row);
    int childCount() const;
    int columnCount() const;
    QVariant data(int column) const;
    void setParent(TreeViewItem* parent);
    TreeViewItem* parent();
    int row() const;
private:
   TreeViewItem* m_parentItem; 
    QList<TreeViewItem*> m_childItems;
    QList<QVariant> m_itemData;
};
2、TreeViewItem.cpp
#include "TreeViewItem.h"
TreeViewItem::TreeViewItem(const QList<QVariant>& data, TreeViewItem* parent)
 {
     this->m_itemData = data;
     this->m_parentItem = parent;
 }TreeViewItem::~TreeViewItem()
 {
     this->m_itemData.clear();
     this->m_parentItem = NULL;
 }void TreeViewItem::appendChild(TreeViewItem* child)
 {
     child->setParent(this);
     this->m_childItems.append(child);
 }void TreeViewItem::deleteAllChild()
 {
     for (int index = 0; index < m_childItems.size(); index++)
     {
         m_childItems[index]->deleteAllChild();
     }
     qDeleteAll(m_childItems);
     m_childItems.clear();
 }TreeViewItem* TreeViewItem::child(int row)
 {
     return m_childItems[row];
 }int TreeViewItem::childCount() const
 {
     return m_childItems.size();
 }int TreeViewItem::columnCount() const
 {
     return m_itemData.size();
 }QVariant TreeViewItem::data(int column) const
 {
     return m_itemData[column];
 }void TreeViewItem::setParent(TreeViewItem* parent)
 {
     m_parentItem = parent;
 }TreeViewItem* TreeViewItem::parent()
 {
     return m_parentItem;
 }int TreeViewItem::row() const
 {
     if (!m_parentItem) { return 0; }    return m_parentItem->m_childItems.indexOf(const_cast<TreeViewItem*>(this));
 }

3、TreeViewModel.h

#pragma once
#ifndef TREEVIEWMODEL_H
 #define TREEVIEWMODEL_H#include <QAbstractItemModel>
 #include <QObject>
 #include <QDebug>
 #include "TreeViewItem.h"#pragma execution_character_set("utf-8")
class TreeViewModel : public QAbstractItemModel
 {
     Q_OBJECTpublic:
    
     TreeViewModel();    ~TreeViewModel();
    void setHeaders(const QStringList& headers)
     {
         m_headers = headers;
     }    void setTreeViewRootItem(TreeViewItem* rootItem)
     {
         m_rootItem = rootItem;
     }    // 必须要重写的五个函数
     Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;    Q_INVOKABLE QModelIndex parent(const QModelIndex& child) const override;
    Q_INVOKABLE int rowCount(const QModelIndex& parent = QModelIndex()) const override;
    Q_INVOKABLE int columnCount(const QModelIndex& parent = QModelIndex()) const override;
    Q_INVOKABLE QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
 private:
    TreeViewItem* itemFromIndex(const QModelIndex& index) const;
private:
    TreeViewItem* m_rootItem;
    QStringList m_headers;
 };#endif // TREEVIEWMODEL_H

4、TreeViewModel.cpp

#include "TreeViewModel.h"
TreeViewModel::TreeViewModel()
 {
     m_rootItem = nullptr;
     m_headers.clear();
 }TreeViewModel::~TreeViewModel()
 {
     m_rootItem->deleteAllChild();
     m_rootItem = NULL;
 }QModelIndex TreeViewModel::index(int row, int column, const QModelIndex& parent) const
 {
     if (!hasIndex(row, column, parent))
     {
         return QModelIndex();
     }    TreeViewItem* treeItem = itemFromIndex(parent);
     TreeViewItem* child = treeItem->child(row); // 第几行就是第几个子节点,TreeView一般都是一行一个节点的
     if (child) {
         return createIndex(row, column, child);
     }
     else {
         return QModelIndex();
     }}
// 返回给定项目的父项目
 QModelIndex TreeViewModel::parent(const QModelIndex& child) const
 {
     if (!child.isValid())
     {
         return QModelIndex();
     }    TreeViewItem* childItem = static_cast<TreeViewItem*>(child.internalPointer());
     TreeViewItem* parentItem = childItem->parent();    if (parentItem == m_rootItem)
     {
         return QModelIndex();
     }    return createIndex(parentItem->row(), 0, parentItem);
 }// 返回给定项目的行数
 int TreeViewModel::rowCount(const QModelIndex& parent) const
 {
     if (parent.column() > 0)
         return 0;    TreeViewItem* item = itemFromIndex(parent);
     return item->childCount();
 }// 返回给定项目的列数
 int TreeViewModel::columnCount(const QModelIndex& parent) const
 {
     if (m_headers.isEmpty())
     {
         // 返回实际的列数 (实际是他返回了0,因为根节点用的是无参的构造),TreeView控件会认为表是空表,不获取数据
         if (parent.isValid())
         {
             return static_cast<TreeViewItem*>(parent.internalPointer())->columnCount();
         }
         else {
             return m_rootItem->columnCount();
         }
     }
     else
     {
         return m_headers.size();
     }
 }QVariant TreeViewModel::data(const QModelIndex& index, int role) const
 {
     if (!index.isValid())
         return QVariant();    TreeViewItem* item = itemFromIndex(index);
     if (role == Qt::DisplayRole)
     {
         return item->data(index.column());
     }
     else if (role == Qt::FontRole)
     {
     }
     else if (role == Qt::TextColorRole) 
     {
     }
     else if (role == Qt::BackgroundRole) 
     {
     }
     else if (role == Qt::TextAlignmentRole)
     {
     }
     return QVariant();
 }// 获取父节点的数据指针,如果parent可用就用parent的节点,如果不可用就用总父节点
 TreeViewItem* TreeViewModel::itemFromIndex(const QModelIndex& parent) const
 {
     if (parent.isValid())
     {
         // internalPointer: 返回一个void *指针,用于模型将索引与内部数据结构关联起来
         TreeViewItem* item = static_cast<TreeViewItem*>(parent.internalPointer());
         return item;
     }
     return m_rootItem;
 }

调用实例:

{
  TreeViewModel* model = new TreeViewModel();
    QStringList headers;
     headers << "1" << "2";
     model->setHeaders(headers);    QVariantList lstVariant;
     TreeViewItem* pRootItem = new TreeViewItem(lstVariant);
     {
         lstVariant.clear();
         lstVariant << "1" << "第一章";
         TreeViewItem* pItem1 = new TreeViewItem(lstVariant);
         pRootItem->appendChild(pItem1);
     }
     {
         lstVariant.clear();
         lstVariant << "2" << "第二章";
         TreeViewItem* pItem2 = new TreeViewItem(lstVariant);
         pRootItem->appendChild(pItem2);
     }
     model->setTreeViewRootItem(pRootItem);    ui.treeView->setModel(model);
}

效果如下所示:

QTreeView 使用QAbstractItemModel实例_QTreeView