一、背景知识
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);