QTreeView是用来显示树型结构的数据,比如目录组织,公司组织架构等,数据量小可以用Qt自带的Model实现,如果数据量大,则需要用自定义的Model实现,下面介绍自定义实现的方法,直接上代码:

#ifndef TYPEDEF_H
#define TYPEDEF_H#include <QVector>// department信息
typedef struct Department_t{QString name;                   // 部门名称int id;                         // 部门id号int number;                     // 部门人数QString preOrganizationName;    // 上级组织名Department_t(){id = 0;number = 0;}QVector<Department_t*> subList;
} Department;// 树列号
enum COLUMN
{COLUMN_NAME = 0,COLUMN_ID,COLUMN_NUM,COLUMN_OrganizationName
};#endif // TYPEDEF_H
#ifndef TREEITEM_H
#define TREEITEM_H#include <QVariant>class TreeItem
{
public:enum Type{UNKNOWN = -1,PROVINCE,PERSON};explicit TreeItem(TreeItem *parent = nullptr);~TreeItem();void addChild(TreeItem *item);void removeChildren();TreeItem *child(int row) { return _children.value(row); }TreeItem *parent() { return _parent; }int childCount() const { return _children.count(); }QVariant data(int column) const;//设置、获取节点存的数据指针void setPtr(void* p) { _ptr = p; }void* ptr() const { return _ptr; }// 保存该节点是其父节点的第几个子节点,查询优化所用void setRow(int row) { _row = row; }// 返回本节点位于父节点下第几个子节点int row() const { return _row; }Type getType() const { return _type; }void setType(const Type &value) { _type = value; }private:QList<TreeItem*> _children;   // 子节点TreeItem *_parent;          // 父节点Type _type;      // 此节点保存的数据类型void* _ptr;     // 存储数据的指针int _row;       // 此item位于父节点中第几个
};#endif // TREEITEM_H
#include "TreeItem.h"
#include "typedef.h"TreeItem::TreeItem(TreeItem *parent): _parent(parent),_type(UNKNOWN),_ptr(nullptr),_row(-1)
{}TreeItem::~TreeItem()
{removeChildren();
}// 在本节点下添加子节点
void TreeItem::addChild(TreeItem *item)
{item->setRow(_children.size());_children.append(item);
}// 清空所有子节点
void TreeItem::removeChildren()
{qDeleteAll(_children);_children.clear();
}// 获取本节点第column列的数据
QVariant TreeItem::data(int column) const
{Department *department = (Department*)_ptr;switch (column) {case COLUMN_NAME: return department->name;case COLUMN_ID: return department->id;case COLUMN_NUM: return department->number;case COLUMN_OrganizationName: return department->preOrganizationName;default:return QVariant();}return QVariant();
}
#ifndef TREEMODEL_H
#define TREEMODEL_H
#include <QAbstractItemModel>class TreeItem;class TreeModel : public QAbstractItemModel
{Q_OBJECT
public:explicit TreeModel(const QStringList& headers, QObject *parent = nullptr);~TreeModel() override;TreeItem *root();QVariant headerData(int section, Qt::Orientation orientation, int role) const override;QVariant data(const QModelIndex &index, int role) const override;QModelIndex index(int row, int column, const QModelIndex &parent) const override;QModelIndex parent(const QModelIndex &index) const override;int rowCount(const QModelIndex &parent) const override;int columnCount(const QModelIndex &parent) const override;private:TreeItem *itemFromIndex(const QModelIndex &index) const;private:QStringList _headers;TreeItem* _rootItem;
};#endif // TREEMODEL_H
#include "TreeModel.h"
#include "TreeItem.h"TreeModel::TreeModel(const QStringList& headers, QObject *parent): QAbstractItemModel(parent)
{_headers = headers;_rootItem = new TreeItem();
}TreeModel::~TreeModel()
{delete _rootItem;
}TreeItem *TreeModel::itemFromIndex(const QModelIndex &index) const
{if (index.isValid()){TreeItem *item = static_cast<TreeItem*>(index.internalPointer());return item;}return _rootItem;
}TreeItem *TreeModel::root()
{return _rootItem;
}// 获取表头数据
QVariant TreeModel::headerData(int section, Qt::Orientation orientation,int role) const
{if (orientation == Qt::Horizontal){if(role == Qt::DisplayRole){return _headers.at(section);}}return QVariant();
}// 获取index.row行,index.column列数据
QVariant TreeModel::data(const QModelIndex &index, int role) const
{if (!index.isValid())return QVariant();TreeItem *item = itemFromIndex(index);if (role == Qt::DisplayRole){return item->data(index.column());}return QVariant();
}// 在parent节点下,第row行,第column列位置上创建索引
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
{if (!hasIndex(row, column, parent))return QModelIndex();TreeItem *parentItem = itemFromIndex(parent);TreeItem *item = parentItem->child(row);if (item)return createIndex(row, column, item);elsereturn QModelIndex();
}// 创建index的父索引
QModelIndex TreeModel::parent(const QModelIndex &index) const
{if (!index.isValid())return QModelIndex();TreeItem *item = itemFromIndex(index);TreeItem *parentItem = item->parent();if (parentItem == _rootItem)return QModelIndex();return createIndex(parentItem->row(), 0, parentItem);
}// 获取索引parent下有多少行
int TreeModel::rowCount(const QModelIndex &parent) const
{if (parent.column() > 0)return 0;TreeItem* item = itemFromIndex(parent);return item->childCount();
}// 返回索引parent下有多少列
int TreeModel::columnCount(const QModelIndex &parent) const
{return _headers.size();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QTreeView>
#include <QHeaderView>
#include <QFile>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include "TreeModel.h"
#include "TreeItem.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);treeView = new QTreeView(this);treeView->setSelectionBehavior(QTreeView::SelectRows);         //一次选中整行treeView->setSelectionMode(QTreeView::SingleSelection);         //单选,配合上面的整行就是一次选单行treeView->setFocusPolicy(Qt::NoFocus);                          //去掉鼠标移到单元格上时的虚线框treeView->header()->setStretchLastSection(true);                //最后一列自适应宽度//treeView->setHeaderHidden(true);                                //设置表头隐藏setCentralWidget(treeView);QVector<Department*> proList = initData();setModel(proList);
}MainWindow::~MainWindow()
{delete ui;
}QVector<Department*>  MainWindow::initData()
{QFile file(":/default2.txt");file.open(QIODevice::ReadOnly);QJsonDocument doc = QJsonDocument::fromJson(file.readAll());QJsonObject obj = doc.object();QJsonArray array = obj.value("nextLevel").toArray();QVector<Department*> depList;qDebug() << "TreeModel::setupModelDataJson==============array.size()====" << array.size() << __LINE__;for(int i = 0; i < array.size(); ++i){QJsonObject subObject = array.at(i).toObject();QJsonArray subArray = subObject.value("nextLevel").toArray();Department *topDepartment = new Department();topDepartment->id = subObject.value("id").toInt();topDepartment->name = subObject.value("name").toString();topDepartment->number = subObject.value("nnt").toInt();topDepartment->preOrganizationName = subObject.value("preOrganizationName").toString();qDebug() << "TreeModel::setupModelDataJson==============subArray.size()====" << subArray.size() << __LINE__;//第二级for(int i = 0; i < subArray.size(); ++i){QJsonObject tempObj = subArray.at(i).toObject();Department *subDepartment = new Department();subDepartment->id = tempObj.value("id").toInt();subDepartment->name = tempObj.value("name").toString();subDepartment->number = tempObj.value("nnt").toInt();subDepartment->preOrganizationName = tempObj.value("preOrganizationName").toString();topDepartment->subList.append(subDepartment);}depList.append(topDepartment);}return depList;
}void MainWindow::setModel(const QVector<Department *> &depList)
{QStringList headers;headers << QStringLiteral("部门名称")<< QStringLiteral("部门Id")<< QStringLiteral("部门人数")<< QStringLiteral("上级部门");TreeModel* model = new TreeModel(headers, treeView);TreeItem* root = model->root();foreach (auto depNode, depList){TreeItem* depItem = new TreeItem(root);depItem->setPtr(depNode); // 保存数据指针root->addChild(depItem);foreach (auto subNode, depNode->subList){TreeItem* subItem = new TreeItem(depItem);subItem->setPtr(subNode);    // 保存数据指针depItem->addChild(subItem);}}treeView->setModel(model);
}

运行结果:

参考:

《QTreeView+QAbstractItemModel自定义模型》:系列教程之三_百里杨的博客-CSDN博客_qtreeview自定义
QTreeView使用总结13,自定义model示例,大大优化性能和内存_逆枫゛的博客-CSDN博客_qtreeview用法
Qt 自定义treemodel_sydnash的博客-CSDN博客_qt自定义treemodel

Qt 可编辑的树模型(Tree Model)的一个实例_qq_21291397的博客-CSDN博客_pyqt treemodel

Qt QTreeView 详解_Mr.codeee的博客-CSDN博客_qt treeview

QJsonObject和QString互转_风起时~微凉的博客-CSDN博客_qjsonobject转qstring

完整源码和测试数据

QTreeView+自定义Model实现示例-C++文档类资源-CSDN下载

QTreeView+自定义Model实现示例相关推荐

  1. 什么是php model类,thinkphp的自定义model类有什么作用?

    请问,thinkphp的自定义model类有什么作用?如: <?php //自定义Modle类 namespace Home\Model; use Think\Model; class StuM ...

  2. boost::geometry模块自定义指针到点示例

    boost::geometry模块自定义指针到点示例 实现功能 C++实现代码 实现功能 boost::geometry模块自定义指针到点示例 C++实现代码 #include <boost/f ...

  3. 【Python】自定义排序函数 - 示例

    自定义排序函数 - 示例 自定义排序规则: def cmp_value_p_code_big(o1, o2):"""排序规则: value大,排前面"" ...

  4. MIGO 行项目屏幕自定义字段增强示例

    继上次抬头屏幕增强(MIGO 抬头屏幕自定义字段增强示例),本文章演示行项目增强示例 实现思路参考标准 MB_MIGO_BADI 增强示例类:CL_EXM_IM_MB_MIGO_BADI 1.创建增强 ...

  5. android 仿360浮动,Android仿360悬浮小球自定义view实现示例

    Android仿360悬浮小球自定义view实现示例 效果图如下: 实现当前这种类似的效果 和360小球 悬浮桌面差不错类似.这种效果是如何实现的呢.废话不多说 ,直接上代码. 1.新建工程,添加悬浮 ...

  6. python如何画贝塞尔曲线_Python使用matplotlib实现绘制自定义图形功能示例

    本文实例讲述了Python使用matplotlib实现绘制自定义图形功能.分享给大家供大家参考,具体如下: 一 代码 from matplotlib.path importPath from matp ...

  7. Qt 3D:高级自定义材质QML示例

    Qt自带集成开发环境(IDE),名为Qt Creator.它可以在Linux.OS X和Windows上运行,并提供智能代码完成.语法高亮.集成帮助系统.调试器和剖析器集成,还集成了所有主要的版本控制 ...

  8. [golang gin框架] 4.自定义Model以及Gin 文件上传

    一.Gin 中自定义 Model 关于 Model 如果应用非常简单的话,我们可以在 Controller 里面处理常见的业务逻辑,但是如果 有一个功能想在多个控制器.或者多个模板里面复用的话,那么就 ...

  9. iOS保存model数据(自定义Model 可以存放到本地)

    1.先创建类目类:继承于NSUserDefaults 2其次前提:保存的model要实现NSCoding 3.在自定义的类目实现这两个方法 -(void)setCustomObj:(id)obj fo ...

  10. Qt学习笔记-----Model/View架构之自定义Model

    Model/View Framework中提供了模型model的抽象基类QAbstractItemModel, 如果需要自定义模型就需要继承这个类并且实现一些必要的函数. 此外,Qt中又提供了QAbs ...

最新文章

  1. 教你用Keras和CNN建立模型识别神奇宝贝!(附代码)
  2. 区块链开发公司能做什么?对企业未来市场有何帮助?
  3. Android Activity动画属性简介
  4. 【原创】贴片电容的测量方法。。。这是我从自己QQ空间转过来的,本人实操!...
  5. GLSL三种修饰符区别与用途(uniform,attribute和varying)
  6. 保护1000万篇原创文章,区块链技术如何做到
  7. Firefox(火狐浏览器)彩蛋
  8. 学python适合什么年龄段的人用_7个现在就该学习Python 的理由【80%的人都不知道】...
  9. [跟我学中小企业架构部署]之八:备份服务器部署
  10. onvif学习笔记6:onvif的OSD坐标小记
  11. Dalvik 虚拟机操作码
  12. BZOJ_1029_[JSOI2007]_建筑抢修_(贪心+优先队列)
  13. python 字典的函数
  14. spring mvc组件以及架构流程详解
  15. 数据分析的3大阶段6大步骤
  16. Python语言程序设计基础 第二版(嵩天著)课后答案第五章
  17. leetcode 714. 买卖股票的时机含手续费 python
  18. ROS生成弓字形覆盖路径点逻辑分析
  19. 用Seam-gen起步(二)
  20. 英国脑科学领域_来自英国A级算法崩溃的数据科学家的4课

热门文章

  1. 一文搞懂PID控制算法
  2. 经济学外文文献在哪查?
  3. 微信小程序音量调节插件
  4. 用matlab对图像进行二维傅里叶变换
  5. LABEL MATRIX里用计数器自动生成流水号和自定义条码格式
  6. 进华为你必须了解的——华为精神
  7. 如何识别服务器网站有病毒,网站有病毒怎么解决?
  8. sns java_JEESNS首页、文档和下载 - Java 开源 SNS 社区系统
  9. 计算机的常见故障处理实验报告,微机系统故障与处理-实验报告.doc
  10. vb.net html元素,vb.net 教程 12-3 HtmlElement类 1