QT之动态加载树节点(QTreeWidget)

之前写过一篇动态加载ComboBox,可参见下面这篇文章
QT之动态加载下拉框(QComboBox)

同理QTreeWidget也可以实现动态加载,在一些异步加载数据,并且数据加载比较耗时,非常实用。

效果

在这里插入图片描述
原理分析
要实现此类效果,要拆解下功能项:
第一步,自定义绘制树的分支图标

//查询qt文档,drawBranches接口可以实现自定义绘制分支图标
virtual void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const

第二步,绘制一个动态图标显示在原来的分支图标上。

源码

TreeWidget.h

class TreeWidget : public QTreeWidget
{
    Q_OBJECT
public:
    explicit TreeWidget(QWidget* parent = nullptr);
    virtual ~TreeWidget();

    /**
     * @brief setGifPath
     * 设置动态图片路径
     * @param _path
     */
    void setGifPath(const QString& _path);

    /**
     * @brief startMovie
     * 开始动画
     */
    void startMovie();

    /**
     * @brief stopMovie
     * 停止播放动画
     */
    void stopMovie();

protected:
    virtual void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const override;

private:
    QMovie *m_movie = nullptr;

};

TreeWidget.cpp

TreeWidget::TreeWidget(QWidget *parent)
{
    m_movie = new QMovie(this);
    connect(m_movie,&QMovie::updated,this,[this](const QRect& rect){
        this->viewport()->update();
    });
}

TreeWidget::~TreeWidget()
{
    if(nullptr != m_movie)
    {
        m_movie->deleteLater();
    }
}

//设置动态图片路径
void TreeWidget::setGifPath(const QString &_path)
{
    m_movie->setFileName(_path);
}

//开始播放动画
void TreeWidget::startMovie()
{
    if(nullptr != m_movie)
    {
        m_movie->start();
    }
}

//停止播放动画
void TreeWidget::stopMovie()
{
    if(nullptr != m_movie)
    {
        m_movie->stop();
    }
    this->viewport()->update();
}

//绘制分支
void TreeWidget::drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const
{
    bool _isload = index.data(Qt::UserRole + 1).toBool();
    if(!_isload)
    {
        return QTreeWidget::drawBranches(painter,rect,index);
    }

    if(nullptr == m_movie)
    {
        return;
    }

    int w = this->indentation();
    auto top = rect.topRight();
    top.setX(top.x() - w);
    QRect _rect(top,rect.bottomRight());

    QPixmap _pix = m_movie->currentPixmap();
    _pix = _pix.scaled(_rect.size(),Qt::KeepAspectRatio,Qt::SmoothTransformation);
    painter->drawPixmap(_rect,_pix);

}

使用

//先构建树
m_tree = new TreeWidget(this);
m_tree->setHeaderHidden(true);
m_tree->setGifPath(":/icon/imgs/loading.gif");

QTreeWidgetItem* item = new QTreeWidgetItem({"root"});
m_tree->addTopLevelItem(item);

QHBoxLayout* _layout = new QHBoxLayout(this);
this->setLayout(_layout);
_layout->addWidget(m_tree);

connect(m_tree,&TreeWidget::itemClicked,this,&CusBranchTreeWidget::slot_itemClicked);


//槽函数及模拟耗时操作
void CusBranchTreeWidget::slot_itemClicked(QTreeWidgetItem *item,int col)
{
    if(item->childCount() != 0)
    {
        return;
    }

    item->setData(0,Qt::UserRole + 1,true);
    m_tree->startMovie();
    //模拟加载数据
    addChildItems(item);
}

//模拟加载数据
void CusBranchTreeWidget::addChildItems(QTreeWidgetItem *parentItem)
{
    QVector<QTreeWidgetItem*> items;
    for(int i = 0; i < 5; i++)
    {
        auto uid = QUuid::createUuid().toString();
        auto item = new QTreeWidgetItem({uid.left(5)});
        items << item;
        //模拟耗时操作
        QEventLoop _loop;
        QTimer::singleShot(500,&_loop,&QEventLoop::quit);
        _loop.exec();
    }

    for(auto& it : items)
    {
        parentItem->addChild(it);
    }

    //停止加载动画
    parentItem->setData(0,Qt::UserRole + 1,false);
    m_tree->stopMovie();
    m_tree->expandItem(parentItem);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值