Qt开发Gif播放器
一、资源下载地址
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播放器的更多相关文章
- Qt+MPlayer音乐播放器开发笔记(一):ubuntu上编译MPlayer以及Demo演示
前言 在ubuntu上实现MPlayer播放器播放音乐. Demo Mplayer MPlayer是一款开源多媒体播放器,以GNU通用公共许可证发布.此款软件 ...
- Qt 简易图片播放器
一.前言 使用 Qt 制作了一个简单的图片播放器,点击 "浏览按钮" 浏览图片所在目录,目录中的所有图片缩小图标和名称会显示在左侧的图片列表中,点击列表中的图片项,可以在右侧区域的 ...
- android开发音乐播放器--Genres和Art album的获取
最近在做一个项目,其中涉及到音乐播放器.当用到Genres和Art album时花费了一些时间才搞定,今天把方法草草列出,以供自己以后忘记时查看,也希望可以帮助碰到同样问题的道友!! 一.Genres ...
- gstreamer应用开发(播放器)之旅
GStreamer开发,主要分为两块:应用开发.插件开发. 插件开发人员,通常是编解码库的作者(做出了编解码库后,希望gstreamer能用起来这个库,因此增加这个适配层).芯片原厂人员(将自家的hw ...
- Android本地视频播放器开发--简易播放器原型
在以前的基础上,将音视频进行合并,音频播放采用OpenSL ES,视频播放采用OpenGL ES2.0进行显示,这次的版本其中音频和视频是在同一个线程,会造成音频断断续续,后续会采用音频使用SDL,视 ...
- Qt实现网络播放器
写了这么多的博客,关于网络的还不算多,经常有人询问一些关于网络传输.制作在线试听及下载音乐.构造及解析数据等的一些问题,今天就在这里一并讲解. 网络操作: 主要涉及:QNetwor ...
- 网页播放音频、视频文件——基于web的html 5的音乐播放器(转载)
文章转载自:开源中国社区 [http://www.oschina.net] 想通过手机客户端(支持 Android.iPhone 和 Windows Phone)访问开源中国:请点这里 HTML5 是 ...
- 基于Qt Phonon模块实现音乐播放器
这次使用Qt实现的是一个本地音乐播放器,可以播放下载在计算机本地的音乐,提供了添加歌曲,歌曲列表,清空列表的功能.默认歌曲列表循环播放.音乐播放的实现主要依赖的是Qt 的多媒体框架phonon.该音乐 ...
- 基于Qt的开源音乐播放器(CZPlayer)
CZPlayer CZPlayer是基于Qt开发的一款功能强大的音乐播放器,该播放器的论坛地址请点击here,目前CZPlayer已经是第四个版本了,历史版本也分别在我的github上, github ...
随机推荐
- [小技巧] Notepad++关闭拼写检查
From : http://blog.csdn.net/xuefeng0707/article/details/18272989 把[插件]-[DSpellCheck]-[Spell Check Do ...
- Java 在Word中创建邮件合并模板并合并文本和图片
Word里面的邮件合并功能是一种可以快速批量操作同类型数据的方式,常见的如数据填充.打印等.其中必不可少的步骤包括用于填充的模板文档.填充的数据源以及实现邮件合并的功能.下面,通过Java程序展示如何 ...
- 理解Python中的闭包
1.定义 闭包是函数式编程的一个重要的语法结构,函数式编程是一种编程范式 (而面向过程编程和面向对象编程也都是编程范式).在面向过程编程中,我们见到过函数(function):在面向对象编程中,我们见 ...
- Shell循环语句for、while、until
Shell循环语句for.while.until 一.条件测试 二.删除字符 三.循环语句 示例1 ...
- VisualEffectGraph基础操作 --创建VEG项目步骤讲解
一:建立VEG项目步骤 首先打开Unity Hub, 使用unity2020.1 新建项目(本技术博客,默认使用unity2020.1 版本演示),选择HDRP 高清渲染管线,确定项目目录与名称. ...
- java集合(5)-List集合
序章 List集合是一个元素有序且可以重复的集合,每个元素对应一个索引,类似于数组的方式,默认是按照添加顺序,所以第一次添加元素索引为0,第二次为1.... 一 Java8改进的List接口和List ...
- 高性能内存图数据库RedisGraph(一)
作为一种简单.通用的数据结构,图可以表示数据对象之间的复杂关系.生物信息学.计算机网络和社交媒体等领域中产生的大量数据,往往是相互连接.关系复杂且低结构化的,这类数据对传统数据库而言十分棘手,一个简单 ...
- 【LeetCode】974. 和可被 K 整除的子数组
974. 和可被 K 整除的子数组 知识点:数组:前缀和: 题目描述 给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续.非空)子数组的数目. 示例 输入:A = [4,5,0,-2,-3, ...
- XIN队算法
XIN队算法 注:名称由莫队算法改编而来 从luogu搬过来了... \(newly\;upd:2021.7.8\) \(newly\;upd:2021.6.6\) OI至高算法,只要XIN队算法打满 ...
- 第二十一篇 -- QTimer实现秒表功能
效果图: 程序一开始就开始计时,当完成了相关功能(在线程中完成)之后,就触发停止信号,停止定时器. time.py #!/usr/bin/env python # _*_ coding: UTF-8 ...