一、资源下载地址

https://www.aliyundrive.com/s/jBU2wBS8poH

本项目路径:项目->免费->Gif播放器(包含整个工程源码,vs2019打开即可编译运行)

二、项目介绍

1、本项目使用Vs2019+Qt库来简易开发一个Gif播放器,Qt项目简易开发环境参考文章:

https://www.cnblogs.com/liangqin/p/15129819.html

本文主要论述功能实现细节。

2、本项目完成的功能如下:

(1)、支持双击Gif文件使用本软件打开进行播放。

(2)、软件支持菜单栏打开文件进行播放。

(3)、支持拖放Gif文件到软件内进行播放。

(4)、软件支持循环播放打开的Gif文件。

(5)、使用左右方向键来切换当前打开文件所在目录的所有图片文件。

(6)、Qt线程的使用。

3、效果展示:

三、项目开始

1、准备工作

搭建一份Qt项目简易开发环境,需要注意的是本项目需要Qt的imageformats库。

2、项目思路

菜单栏打开文件、拖拽文件到软件内、双击文件打开可以认为是要获取当前要播放的文件名以及文件所在目录的所有图片文件名,而左右方向键切换则是要更改当前要播放的文件名。我们可以在用户操作后,使用成员变量记录当前播放的文件名以及一个文件名列表和当前播放文件在列表中的位置。然后开启一个线程来循环获取当前需要播放的文件名来读取文件进行播放。

3、界面设计

使用designer来设计我们的UI,增加一个菜单栏打开按钮和添加一个label来显示图像。最后对我们添加的控件进行布局,让label可以随着窗口缩放来自动缩放。如图所示:

4、当前播放文件名与文件名列表获取实现:

void GuiGifView::changeFileName(QString fileName)
{
//Qt获取的文件路径分隔符是/,编码是utf8
m_file_name = fileName;
m_file_change_flag = 1;
} void GuiGifView::setFileName(QString fileName)
{
changeFileName(fileName); //获取路径
QString fileDir = fileName.left(fileName.lastIndexOf("/") + 1); //获取该路径下的图片文件
QDir dir(fileDir);
QStringList nameFilters;
nameFilters << "*.gif" << "*.jpg" << "*.png";
QStringList files = dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name); QList<QString>::Iterator it = files.begin(),itend = files.end();
int i = 0; m_file_list.clear(); for (;it != itend; it++,i++)
{
QString file = fileDir;
file += *it;
m_file_list.append(file);
if (file == fileName)
m_cur_file_idx = i;
} return;
}

5、菜单栏打开文件槽函数实现:

void GuiGifView::on_m_openFile_button_triggered()
{
QString filename = QFileDialog::getOpenFileName();
if (filename.toStdString() == "")
return; setFileName(filename); return ;
}

6、文件拖拽实现:

/*拖放分为拖动(Drag)和放下(Drop)两种操作。数据拖动时会被存储为MIME(Multipurpose-
* Internet Mail Extensions)类型,在Qt使用QMimeData类来表示MIME类型数据,并还用
* QDrag类来完成数据的转换,而整个拖放操作都是在几个鼠标事件和拖放事件中完成.
*/
void GuiGifView::dragEnterEvent(QDragEnterEvent* event)//拖动事件
{
//可打开.txt,.h,.cpp文件
if (event->mimeData()->hasUrls()) //数据中是否包含URL
event->acceptProposedAction(); //如果是则接受动作
else
event->ignore();
} void GuiGifView::dropEvent(QDropEvent* event)//放下事件
{
const QMimeData* mineData = event->mimeData();//获取MIME数据
if (mineData->hasUrls()) //如数据中包含URL
{
QList<QUrl>urlList = mineData->urls(); //获取URL列表
if (urlList.isEmpty())
return;
//将其中第一个URL表示为本地文件路径
QString filename = urlList.at(0).toLocalFile();
if (filename.isEmpty())
return; setFileName(filename);
}
}

7、左右方向键切换文件名实现:

void GuiGifView::keyPressEvent(QKeyEvent  *event)
{
//左右按键切换当前文件目录下的图片
if(event->key() == Qt::Key_Left)
{
m_cur_file_idx -= 1;
if(m_cur_file_idx < 0)
m_cur_file_idx = m_file_list.count() - 1; changeFileName(m_file_list.at(m_cur_file_idx));
}
else if(event->key() == Qt::Key_Right)
{
m_cur_file_idx += 1;
if(m_cur_file_idx >= m_file_list.count())
m_cur_file_idx = 0; changeFileName(m_file_list.at(m_cur_file_idx));
}
}

8、label显示图像接口:

void GuiGifView::LabelShowImg(QImage* img)
{
if(img != NULL)
{
ui.m_showImg_label->setPixmap(QPixmap::fromImage(*img));
}
}

9、开启一个线程来播放图像:

void GuiGifViewThread::run()
{
while (1)
{
//程序退出时终止线程
if(m_gui->isExit())
return ; QString file_name = m_gui->getFileName();
if(file_name.toStdString() == "")
{
QThread::msleep(40);
continue;
} QImageReader reader(file_name);
reader.setDecideFormatFromContent(true);
int nCount = reader.imageCount(); int sleep_time = 40;
int sleep_flag = 0; for (int i = 0; i < nCount; ++i)
{
//程序退出时终止线程
if(m_gui->isExit())
return ; //文件名改变重新读取文件
if(m_gui->fileIsChange())
break ; // 跳到顺序号为i的图像
bool ret = reader.jumpToImage(i);
QImage image;
if(reader.read(&image))
{
//图像缩放为label大小
int labelw = m_gui->getImgLabelW();
int labelh = m_gui->getImgLabelH();
int Owidth = image.width();
int Oheight = image.height();
int Fwidth,Fheight;//缩放后的图片大小
float Mul;//记录图片与label大小的比例,用于缩放图片
if(Owidth*1.0/labelw>=Oheight*1.0/labelh)
Mul=Owidth*1.0/labelw;
else
Mul=Oheight*1.0/labelh;
Fwidth=Owidth*1.0/Mul;
Fheight=Oheight*1.0/Mul;
QImage scaledimg;
scaledimg = image.scaled(Fwidth,Fheight,Qt::KeepAspectRatio); //只能使用emit方式操作控件,直接操作控件会死机,这里会等待槽函数结束才继续运行(Qt::BlockingQueuedConnection)
emit m_gui->sigLabelShowImg(&scaledimg); if(reader.nextImageDelay() > 0)
sleep_time = reader.nextImageDelay(); QThread::msleep(sleep_time);
sleep_flag = 1;
}
} if(sleep_flag == 0)
QThread::msleep(sleep_time);
}
}

10、结束语

上面的代码只是本项目中重要的部分,其余代码可以下载工程后进行查看。需要注意的是开启一个线程来操作界面的时候需要使用emit的方式,否则会死机。

Qt开发Gif播放器的更多相关文章

  1. Qt+MPlayer音乐播放器开发笔记(一):ubuntu上编译MPlayer以及Demo演示

    前言   在ubuntu上实现MPlayer播放器播放音乐.   Demo                Mplayer   MPlayer是一款开源多媒体播放器,以GNU通用公共许可证发布.此款软件 ...

  2. Qt 简易图片播放器

    一.前言 使用 Qt 制作了一个简单的图片播放器,点击 "浏览按钮" 浏览图片所在目录,目录中的所有图片缩小图标和名称会显示在左侧的图片列表中,点击列表中的图片项,可以在右侧区域的 ...

  3. android开发音乐播放器--Genres和Art album的获取

    最近在做一个项目,其中涉及到音乐播放器.当用到Genres和Art album时花费了一些时间才搞定,今天把方法草草列出,以供自己以后忘记时查看,也希望可以帮助碰到同样问题的道友!! 一.Genres ...

  4. gstreamer应用开发(播放器)之旅

    GStreamer开发,主要分为两块:应用开发.插件开发. 插件开发人员,通常是编解码库的作者(做出了编解码库后,希望gstreamer能用起来这个库,因此增加这个适配层).芯片原厂人员(将自家的hw ...

  5. Android本地视频播放器开发--简易播放器原型

    在以前的基础上,将音视频进行合并,音频播放采用OpenSL ES,视频播放采用OpenGL ES2.0进行显示,这次的版本其中音频和视频是在同一个线程,会造成音频断断续续,后续会采用音频使用SDL,视 ...

  6. Qt实现网络播放器

        写了这么多的博客,关于网络的还不算多,经常有人询问一些关于网络传输.制作在线试听及下载音乐.构造及解析数据等的一些问题,今天就在这里一并讲解.   网络操作:     主要涉及:QNetwor ...

  7. 网页播放音频、视频文件——基于web的html 5的音乐播放器(转载)

    文章转载自:开源中国社区 [http://www.oschina.net] 想通过手机客户端(支持 Android.iPhone 和 Windows Phone)访问开源中国:请点这里 HTML5 是 ...

  8. 基于Qt Phonon模块实现音乐播放器

    这次使用Qt实现的是一个本地音乐播放器,可以播放下载在计算机本地的音乐,提供了添加歌曲,歌曲列表,清空列表的功能.默认歌曲列表循环播放.音乐播放的实现主要依赖的是Qt 的多媒体框架phonon.该音乐 ...

  9. 基于Qt的开源音乐播放器(CZPlayer)

    CZPlayer CZPlayer是基于Qt开发的一款功能强大的音乐播放器,该播放器的论坛地址请点击here,目前CZPlayer已经是第四个版本了,历史版本也分别在我的github上, github ...

随机推荐

  1. Tars | Win10下Docker部署TarsJava(SpringBoot)全过程及踩坑记录

    @ 目录 前言 1. 相关环境版本: 坑点一:VMware与Win10 Docker冲突 坑点二:20.版本TarsJava(SpringBoot)依赖文件缺失 2. Docker安装: 坑点三:Do ...

  2. 锁分析 Lock

    锁分析 Lock NonReentrantLock ReadLock 共享锁 ReentrantLock 重入锁 排他锁 sync.lock 返回值为void,表示如无异常发生都认为锁获取成功 Fai ...

  3. Java实验项目二——小学生考试系统(简单四则运算)

    Program:设计实现一个小学生数学考试系统,完成随机出题(简单的四则运算),学生答题,自动判分的功能. Description:代码如下: 1 /* 2 * Description:面向考试系统建 ...

  4. 了解Javascript中函数作为对象的魅力

    前言 Javascript赋予了函数非常多的特性,其中最重要的特性之一就是将函数作为第一型的对象.那就意味着在javascript中函数可以有属性,可以有方法, 可以享有所有对象所拥有的特性.并且最重 ...

  5. 《PHP扩展学习系列》系列分享专栏

    <PHP扩展学习系列>系列分享专栏   <PHP扩展学习系列>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read/20177 ...

  6. Kubernetes 1.13.3 部署 Prometheus+Grafana-7.5.2(最新版本踩坑)

    本教程直接在 Kubernetes 1.13.3 版本上安装 Prometheus 和 Grafana-7.5.2,至于它们的原理和概念就不再赘述,这里就直接开始操作. Git 下载相关 YAML 文 ...

  7. C语言:数据类型转换 自动转换 强制转换

    数据类型转换就是将数据(变量.数值.表达式的结果等)从一种类型转换为另一种类型. 自动类型转换 自动类型转换就是编译器默默地.隐式地.偷偷地进行的数据类型转换,这种转换不需要程序员干预,会自动发生.1 ...

  8. WIN10 报错及解决方法

    你的电脑/设备需要修复,无法加载操作系统,原因是关键系统驱动程序丢失或包含错误 \windows\system32\drivers\zklvv.sys 错误代码:0XC000007b 解决方法: 用U ...

  9. mybatis-5-关联查询

    外键查询 1.回忆外键约束 注意要在tbl_dept中添加外键 #添加外键约束 # 此处Employee为外键表,dept为主键表 # 删除Employee的数据不会影响dapt,而删除dept一定会 ...

  10. YsoSerial 工具常用Payload分析之CC3(二)

    这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...