前言
通过Qt做一些GUI项目时,有时需要去展示一些gif动态图至界面,如果将显示动态图的操作一并放置在主线程,即窗口显示线程中时,当需要加载的动态图数量多、尺寸大时,同时拖动窗口有可能产生卡顿的现象,且动态图的显示也有可能会卡顿。因此考虑设置一个子线程专用于动态图的显示。
Qt中多线程的实现主要有以下两种方式:
(1)继承QThread类,重写run()方法
(2)继承QObject类,通过movetoThread()方法实现
本案例使用第(1)种方式实现动态图的多线程显示。
效果
效果如下图所示,在一个窗口中同时显示3张gif动态图,拖拽窗口,整体并不卡顿。
核心代码
创建一个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;
}