六十三、自定义树状图模型

一、背景知识

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);

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值