在平时浏览网站,或者使用软件的时候,经常可以见到:在点击了某个按钮之后,按钮上会显示动图以及提示文字。在QT中,比较常见且简单的做法就是:给按钮设置一个layout,然后在这个layout里面添加QLabel(作为QMovie的载体),以及用于显示文字的QLabel。该方案可参考:https://blog.csdn.net/hellokandy/article/details/120043562
但本文将采取另外一种方式(编写一个用于播放Gif 的QPushButton类)来实现,原生的按钮只要提升为该类即可。
1、效果图
2、GifPushButton
1、GifPushButton.h
#ifndef GIFPUSHBUTTON_H
#define GIFPUSHBUTTON_H
#include <QWidget>
#include <QPushButton>
class QMovie;
class GifPushButton : public QPushButton
{
Q_OBJECT
public:
explicit GifPushButton(QWidget *parent = nullptr);
~GifPushButton(){}
//
void SetMovie(const QString &fileName);
void SetMovie(QMovie *movie);
QMovie *GetMovie() const;
//
void Start();
void Stop();
//
signals:
void movieChanged();
protected:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
private slots:
void OnFrameChanged(int frameNumber);
private:
QMovie *m_movie = nullptr;
bool m_movieResized = false;
};
#endif // GIFPUSHBUTTON_H
2、GifPushButton.cpp
#include "gifpushbutton.h"
#include <QMovie>
#include <QDebug>
GifPushButton::GifPushButton(QWidget *parent)
: QPushButton(parent)
, m_movie(nullptr)
{
}
void GifPushButton::SetMovie(const QString &fileName)
{
auto movie = new QMovie(this);
movie->setFileName(fileName);
SetMovie(movie);
}
void GifPushButton::SetMovie(QMovie *movie)
{
if(!movie){
return;
}
if(movie == m_movie){
return;
}
if(m_movie)
{
m_movie->stop();
disconnect(movie, &QMovie::frameChanged, this, &GifPushButton::OnFrameChanged);
}
if(movie->parent() != this){
movie->setParent(this);
}
movie->jumpToFrame(0);
m_movie = movie;
connect(movie, &QMovie::frameChanged, this, &GifPushButton::OnFrameChanged);
connect(movie, &QMovie::destroyed, this, [](QObject *object){
Q_UNUSED(object);
qDebug() << "movie destroyed";
});
//
emit movieChanged();
}
QMovie *GifPushButton::GetMovie() const
{
return m_movie;
}
void GifPushButton::Start()
{
if(m_movie){
m_movie->start();
}
}
void GifPushButton::Stop()
{
if(m_movie){
m_movie->stop();
setIcon(QIcon());
}
}
void GifPushButton::showEvent(QShowEvent *event)
{
if(m_movie){
m_movie->start();
}
//GifPushButton::showEvent(event);
}
void GifPushButton::hideEvent(QHideEvent *event)
{
if(m_movie){
m_movie->stop();
}
//GifPushButton::hideEvent(event);
}
void GifPushButton::OnFrameChanged(int frameNumber)
{
if(!m_movie){
return;
}
if(!m_movieResized)
{
int len = qMin(width(), height());
QSize sz = QSize(len, len);
m_movie->setScaledSize(sz);
QRect rect = m_movie->frameRect();
//
m_movieResized = true;
qDebug() << sz << rect.size();
}
QPixmap pix = m_movie->currentPixmap();
setIcon(QIcon(pix));
}
3、如何使用
#include "maindialog.h"
#include "ui_maindialog.h"
MainDialog::MainDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::MainDialog)
{
ui->setupUi(this);
//
ui->button_loading->setFixedSize(150, 36);
ui->button_downloading->setFixedSize(150, 36);
ui->button_dancing->setFixedSize(150, 36);
//
ui->button_loading->SetMovie(":/image/loading.gif");
ui->button_downloading->SetMovie(":/image/downloading.gif");
ui->button_dancing->SetMovie(":/image/dancing.gif");
//from qss style
ui->button_loading->setProperty("button_type", "120x48");
}
MainDialog::~MainDialog()
{
delete ui;
}
void MainDialog::on_button_start_clicked()
{
ui->button_loading->Start();
}
void MainDialog::on_button_stop_clicked()
{
ui->button_loading->Stop();
}