`
tcspecial
  • 浏览: 895425 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

QTreeView 使用自定义Model

    博客分类:
  • QT
阅读更多

        QT对于列表和表格结构都有相应的model实现, 唯独对QTreeView没有提供任何默认实现,只能子类化QAbstractItemModel. 由于树形结构比较复杂,层次结构不固定,用MVC框架实现的确比较费劲. 还好QT提供的这个例子能够处理很多通用问题. 可直接拿过来用, 由于示例代码看起来比较费劲,特笔记记录: 

       QT示例参见$(QTDIR)\examples\itemviews\simpletreemodel:

       Tree Model       

 

一. 树形结构体定义 treeitem.h 

/**
 * @brief 通用树形结构类
 */
class TreeItem
{
public:
    TreeItem(const QList<QVariant> &data,TreeItem *parent=0 );
    ~TreeItem();

    void appendChild(TreeItem *child);
    TreeItem *child(int row);
    int childCount() const;
    int columnCount() const;
    QVariant data(int column) const;
    int row() const;
    TreeItem *parent();

private:
    TreeItem *parentItem;  // 父结点
    QList<TreeItem*> childItems; // 子结点列表
    QList<QVariant> itemData; // 子节点对应数据
};

 

二. 树形model实现

#include <QAbstractItemModel>
#include "TreeItem.h"

class TagTreeModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    TagTreeModel(QObject *parent = 0);
    ~TagTreeModel();

    QVariant data(const QModelIndex &index, int role) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const;
    QModelIndex index(int row, int column,
                      const QModelIndex &parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex &index) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;

    // 构建模型数据
    void setupModelData(TreeItem *parent);

    // 更新模型数据
    void updateData();

private:
    TreeItem *rootItem; // 最顶层顶根节点(一个无效的QModelIndex)
};

 

    TagTreeModel.cpp 

#include "TagTreeModel.h"
#include <QtGui>

TagTreeModel::TagTreeModel(QObject *parent):QAbstractItemModel(parent)
{
    rootItem=NULL;

    updateData();
}

TagTreeModel::~TagTreeModel()
{
    delete rootItem;
}

void TagTreeModel::updateData()
{
    // 废弃旧的模型数据
    if(rootItem)
    {
        delete rootItem;
        rootItem=NULL;
    }

    QList<QVariant> rootData;
    rootData<<"Tag"<<"Type";

    rootItem=new TreeItem(rootData);
    setupModelData(rootItem);

    // 刷新模型
    reset();
}

QVariant TagTreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    // 添加图标
    if(role==Qt::DecorationRole&&index.column()==0)
            return QIcon("images/fold.png");

    // 显示节点数据值
    if(role==Qt::DisplayRole)
    {
        TreeItem *item=static_cast<TreeItem*>(index.internalPointer());
         return item->data(index.column());
    }

    return QVariant();
}

Qt::ItemFlags TagTreeModel::flags(const QModelIndex &index) const
{
    if(!index.isValid())
        return 0;

    return Qt::ItemIsEnabled|Qt::ItemIsSelectable;
}

QVariant TagTreeModel::headerData(int section, Qt::Orientation orientation,int role) const
{
    if(orientation==Qt::Horizontal&&role==Qt::DisplayRole)
        return rootItem->data(section);

    return QVariant();
}

QModelIndex TagTreeModel::index(int row, int column,const QModelIndex &parent) const
{
    if(!hasIndex(row,column,parent))
        return QModelIndex();

    TreeItem *parentItem;
    if(!parent.isValid())
    {
        parentItem=rootItem;
    }else
    {
        parentItem=static_cast<TreeItem*>(parent.internalPointer());
    }

    TreeItem *childItem=parentItem->child(row);
    if(childItem)
        return createIndex(row,column,childItem); // 展开树形,为子节点建立索引
    else
        return QModelIndex();
}

QModelIndex TagTreeModel::parent(const QModelIndex &index) const
{
    if(!index.isValid())
        return QModelIndex();

    TreeItem *childItem=static_cast<TreeItem*>(index.internalPointer());
    TreeItem *parentItem=childItem->parent();

    // 顶层节点,直接返回空索引
    if(parentItem==rootItem)
        return QModelIndex();

    // 为父结点建立索引
    return createIndex(parentItem->row(),0,parentItem);
}

int TagTreeModel::rowCount(const QModelIndex &parent) const
{
    TreeItem *parentItem;

    if(!parent.isValid())
        parentItem=rootItem;
    else
        parentItem=static_cast<TreeItem*>(parent.internalPointer());

    return parentItem->childCount(); // 返回父结点下子结点数目
}

int TagTreeModel::columnCount(const QModelIndex &parent ) const
{
    return rootItem->columnCount();
}

// 设置模型数据,构建包含10个根结点,每个根结点包含两个子节点的树形结构
void TagTreeModel::setupModelData(TreeItem *parent)
{
    for(int i=0;i<10;i++)
    {
        QList<QVariant> datas;
        datas<<QString("设备-%1").arg(i+1)<<QString("类型-%1").arg(i+1);

        // 主结点下挂两个子节点
        TreeItem *primary=new TreeItem(datas,parent);
        parent->appendChild(primary);

        for(int j=0;j<2;j++)
        {
            QList<QVariant> ds;
            ds<<QString("子设备-%1").arg(j+1)<<QString("子类型-%1").arg(j+1);

            primary->appendChild(new TreeItem(ds,primary));
        }
    }
}

 

 

  • 大小: 28.5 KB
分享到:
评论
2 楼 tcspecial 2016-07-25  
陈宇飞 写道
reset()为什么不可以用了,版本低了,还是头文件呢

本文是在Qt4.8.4上测试的,Qt5的 QAbstractItemModel::reset() 也是存在的。应该与版本关系不大
1 楼 陈宇飞 2016-07-16  
reset()为什么不可以用了,版本低了,还是头文件呢

相关推荐

Global site tag (gtag.js) - Google Analytics