QT之动态加载下拉框(QComboBox)

QT之动态加载下拉框(QComboBox)

  • 简介
  • 效果
  • 原理分析
  • 实现

简介

这两天遇到一个需求,需要下拉选项中动态加载一些数据,实现之后感觉挺有意思,特此记录一下。

效果

还是先看下效果,源码也放在文末了
QT之动态加载下拉框(QComboBox)_第1张图片

原理分析

要实现此类效果,要拆解下功能项:

  • 第一步,下拉选项的item要能够显示动态图片
  • 第二步,拦截ComboBox的鼠标事件,使得再点击特定得节点后可以执行一些额外得操作,并且不隐藏下拉框

实现

分解了功能点,接下来就可以实现代码了:
首先让QListWidgetItem能够显示动态图标,QT控件得setIcon接口原生是不支持显示动态图片的,那怎么实现呢?
我的方法是,封装一个MyListWidgetItem类,类成员包含QListWidgetItem,并且使用QMovie播放gif图片,获取每帧并实时更新Icon。实现代码如下:
Ps:有大佬有更好的办法望指教
ListWidgetItem.h

#ifndef ListWidgetItem_H
#define ListWidgetItem_H

#include 
#include 
#include 
#include 

class QListWidgetItem;
class ListWidgetItem : public QObject
{
    Q_OBJECT
public:
    explicit ListWidgetItem(const QString& text,QObject *parent = nullptr);
    explicit ListWidgetItem(const QIcon& _icon,const QString& text,QObject *parent = nullptr);
    ~ListWidgetItem();

    void setGifPath(const QString& path);
    QListWidgetItem* getItem();

    void start();
    void stop();

protected slots:
    void slot_timeOut();

private:
    void connectAll();

private:
    QListWidgetItem *m_item = nullptr;
    QIcon m_icon;
    QString m_gifPath;

    QTimer m_timer;
    QMovie m_movie;

};

#endif // ListWidgetItem_H

ListWidgetItem.cpp

#include "ListWidgetItem.h"

#include 
#include 

ListWidgetItem::ListWidgetItem(const QString &text, QObject *parent)
    : QObject(parent)
{
    m_item = new QListWidgetItem(text);
    m_item->setData(Qt::UserRole+1,qint64(this));
    connectAll();
}

ListWidgetItem::ListWidgetItem(const QIcon &_icon, const QString &text, QObject *parent) : QObject(parent)
{
    m_item = new QListWidgetItem(_icon,text);
    m_item->setData(Qt::UserRole+1,qint64(this));
    m_icon = _icon;
    connectAll();
}

ListWidgetItem::~ListWidgetItem()
{

}

void ListWidgetItem::setGifPath(const QString &path)
{
    m_gifPath = path;
    m_movie.setFileName(m_gifPath);
}

QListWidgetItem *ListWidgetItem::getItem()
{
    return m_item;
}

void ListWidgetItem::start()
{
//    m_movie.setSpeed(100);
    m_movie.start();
    m_timer.start(30);
}

void ListWidgetItem::stop()
{
    m_movie.stop();
    m_timer.stop();
    m_item->setIcon(m_icon);
}

void ListWidgetItem::slot_timeOut()
{
    if(nullptr == m_item)
    {
        return;
    }

    QPixmap pix = m_movie.currentPixmap();
    m_item->setIcon(pix);
//    m_timer.stop();
}

void ListWidgetItem::connectAll()
{
    connect(&m_timer,&QTimer::timeout,this,&ListWidgetItem::slot_timeOut);
}

然后,过滤ComboBox的鼠标事件,并实现播放动画和其他操作,实现方式为:
重写QComboBox,并为其view()->viewport()安装事件过滤器,监听鼠标弹起事件QEvent::MouseButtonRelease。关键代码如下

DynamicBox::DynamicBox(QWidget *parent)
    : QComboBox(parent)
{
    if(this->view() != nullptr)
    {
        this->view()->installEventFilter(this);
        this->view()->viewport()->installEventFilter(this);
    }
}

bool DynamicBox::eventFilter(QObject *o, QEvent *e)
{
    auto index = this->view()->currentIndex();
    if(e->type() == QEvent::MouseButtonRelease && index.data().toString() == "加载更多")
    {
        auto item = static_cast<QListWidgetItem*>(index.internalPointer());
        if(nullptr == item)
        {
            return false;
        }

        auto Myitem = (ListWidgetItem*)(item->data(Qt::UserRole+1).toLongLong());
        if(nullptr == Myitem)
        {
            return false;
        }
        Myitem->start();
        QTimer::singleShot(3000,this,[Myitem,this](){
            Myitem->stop();
            emit signal_test(this);
        });

        return true;
    }
    return QComboBox::eventFilter(o,e);
}

做完这些后就能实现图中效果啦~

源码下载在这里

你可能感兴趣的:(qt,开发语言,c++)