Qt 多线程显示gif动态图


前言

通过Qt做一些GUI项目时,有时需要去展示一些gif动态图至界面,如果将显示动态图的操作一并放置在主线程,即窗口显示线程中时,当需要加载的动态图数量多、尺寸大时,同时拖动窗口有可能产生卡顿的现象,且动态图的显示也有可能会卡顿。因此考虑设置一个子线程专用于动态图的显示。

Qt中多线程的实现主要有以下两种方式:
(1)继承QThread类,重写run()方法
(2)继承QObject类,通过movetoThread()方法实现

本案例使用第(1)种方式实现动态图的多线程显示。


效果

效果如下图所示,在一个窗口中同时显示3张gif动态图,拖拽窗口,整体并不卡顿。
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

核心代码

创建一个gifThread类继承于QThread,构造函数为gifThread(const QString gifpath);形参为动态图的地址。
该类还具有两个变量QLabel *label,用于显示图片的容器,QMovie *gif为动图类,用于对动图进行参数设置。

gifThread.h

#ifndef GIFTHREAD_H
#define GIFTHREAD_H

#include <QObject>
#include <QThread>
#include <QMovie>
#include <QLabel>
#include <QDebug>

class gifThread:public QThread
{
    Q_OBJECT

public:
    gifThread(const QString gifpath);
    QString gifPath;
    QLabel *label;
    QMovie *gif;
    void run();
};

#endif // GIFTHREAD_H

gifThread.cpp

在gifThread构造函数中传入gif的地址,并且申请一块内存空间用于存放显示动图用的QLabel。
重写run()函数,在run()函数中new出QMovie,设置其大小、播放速度、以及开始,在while(1)循环中的qApp->processEvents();用于使得动图不断地播放。

#include "gifThread.h"

gifThread::gifThread(const QString gifpath)
{
    gifPath = gifpath;
    label = new QLabel;
}

void gifThread::run()
{
    gif = new QMovie(gifPath);
    label->setMovie(gif);
    gif->setScaledSize(QSize(400,300));
    gif->setSpeed(500);
    gif->start();
    while(1)
    {
//        qDebug()<<currentThreadId();
//        msleep(100);
        qApp->processEvents();
    }
}

widget.h

在Widget类的声明中,申明三个gifThread变量gifThread *t1, *t2, *t3;

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QMovie>
#include "gifThread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    gifThread *t1, *t2, *t3;
};
#endif // WIDGET_H

widget.cpp

在Widget类的构造函数中,分别new出三个gifThread对象
注意,t1->label = ui->label_2;左右两边内容方向不能反

#include "widget.h"
#include "ui_widget.h"


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    t1 = new gifThread(":/2.gif");
    t2 = new gifThread(":/1.gif");
    t3 = new gifThread(":/3.gif");
    //label的内容显示,两边内容不能反
    t1->label = ui->label_2;
    t2->label = ui->label;
    t3->label = ui->label_3;
    //开启线程
    t1->start();
    t2->start();
    t3->start();
}

Widget::~Widget()
{
    delete ui;
}

参考

本文参考了此篇博客https://www.cnblogs.com/tlsdba/p/2565559.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wang_chao118

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值