一、背景知识

QTreeView 是没有对应的模型对象。

二、自定义树状图Model

CustomTreeModel.h

#ifndef CUSTOMTREEMODEL_H
#define CUSTOMTREEMODEL_H

#include <QObject>
#include <QAbstractItemModel>

class Node {
public:
enum Type {
AA = 0,
BB,
CC,
DD
};
Node(Type type, const QString &nodeName = "");
~Node();
Type type;
QString nodeName;
Node *parent;
QList<Node*> children;
};

class CustomTreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit CustomTreeModel(QObject *parent = 0);
~CustomTreeModel();
void setRootNode(Node *node);

public:
QModelIndex index(int row, int column, const QModelIndex &parent) const Q_DECL_OVERRIDE;
QModelIndex parent(const QModelIndex &child) const Q_DECL_OVERRIDE;
int rowCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;

private:
Node *rootNode;
Node *nodeFromIndex(const QModelIndex &index)const;
};

#endif // CUSTOMTREEMODEL_H

CustomTreeModel.cpp

#include "customtreemodel.h"

Node::Node(Node::Type type, const QString &nodeName) :
type(type),
nodeName(nodeName),
parent(0)
{

}

Node::~Node()
{
qDeleteAll(children);
}

CustomTreeModel::CustomTreeModel(QObject *parent) : QAbstractItemModel(parent)
{
rootNode = new Node(Node::AA, "rootNode");
}

CustomTreeModel::~CustomTreeModel()
{
delete rootNode;
}

void CustomTreeModel::setRootNode(Node *node)
{
delete rootNode;
rootNode = node;
}

QModelIndex CustomTreeModel::index(int row, int column, const QModelIndex &parent) const
{
if (!rootNode && row > 0 && column > 0) {
return QModelIndex();
}
Node *parentNode;
if (!parent.isValid()) {
parentNode = rootNode;
} else {
parentNode = nodeFromIndex(parent);
}
Node *childNode = parentNode->children.value(row);
if (!childNode) {
return QModelIndex();
}
return createIndex(row, column, childNode);
}

QModelIndex CustomTreeModel::parent(const QModelIndex &child) const
{
Node *childNode = nodeFromIndex(child);
if (!childNode) {
return QModelIndex();
}
Node *parentNode = childNode->parent;
if (!parentNode) {
return QModelIndex();
}
Node *grandParentNode = parentNode->parent;
if (!grandParentNode) {
return QModelIndex();
}
int row = grandParentNode->children.indexOf(parentNode);
//默认树只有1列
return createIndex(row, 0, parentNode);
}

int CustomTreeModel::rowCount(const QModelIndex &parent) const
{
Node *parentNode = nodeFromIndex(parent);
if (!parentNode) {
return 0;
}
return parentNode->children.count();
}

int CustomTreeModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
//设置列数
return 2;
}

QVariant CustomTreeModel::data(const QModelIndex &index, int role) const
{
if (Qt::DisplayRole != role) {
return QVariant();
}
Node *node = nodeFromIndex(index);
if (!node) {
return QVariant();
}
if (index.column() == 0) {
switch (node->type) {
case Node::AA:
return "root";
break;
case Node::BB:
return "node1";
break;
case Node::CC:
return "node2";
break;
case Node::DD:
return "node3";
break;
default:
return "UnKnown";
break;
}
} else if (index.column() == 1) {
return node->nodeName;
}
}

QVariant CustomTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (Qt::Horizontal == orientation && Qt::DisplayRole == role) {
switch (section) {
case 0:
return "Node";
break;
case 1:
return "Value";
break;
default:
return QVariant();
break;
}
}
return QVariant();
}

Node *CustomTreeModel::nodeFromIndex(const QModelIndex &index) const
{
if (index.isValid()) {
return static_cast<Node*>(index.internalPointer());
} else {
return rootNode;
}
}

三、使用

main.cpp

//初始化所有节点
Node *rootNode = new Node(Node::AA, "根节点");
Node *node1 = new Node(Node::BB, "子节点");
Node *node2 = new Node(Node::BB, "子节点");
Node *node3 = new Node(Node::CC, "孙子节点");
//指向父节点
rootNode->parent = 0;
node1->parent = rootNode;
node2->parent = rootNode;
node3->parent = node1;

//指向子节点
QList<Node*> nodes;
nodes.append(node1);
nodes.append(node2);
rootNode->children = nodes;
QList<Node*> nodes1;
nodes1.append(node3);
node1->children = nodes1;

//初始化数据模型
CustomTreeModel *model = new CustomTreeModel(this);
//设置根节点
model->setRootNode(rootNode);
ui->treeView->setModel(model);
ui->treeView->expandAll();

ui->comboBox->setModel(ui->treeView->model());
ui->comboBox->setView(ui->treeView);

六十三、自定义树状图模型_子节点