一、资源下载地址

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的方式,否则会死机。

最新文章

  1. UI第九节——UIProgressView
  2. 添加office权限时找不到ofice,com组件的方法
  3. Activiti系列: 如何在web中使用activiti和sql server
  4. Chrome 文件另存为和打开本地资源时会卡死的问题
  5. java提高篇---Iterator
  6. 黑金开发板上开发的PWM
  7. C++ for循环效率
  8. Servlet获取当前服务器的实际路径
  9. Hibernate 注意命名与数据库关键字的冲突 处理方法
  10. 【转】android官方侧滑菜单DrawerLayout详解
  11. redux-applyMiddleware实现理解+自定义中间件
  12. PHP之路——微信公众号授权获取用户信息
  13. Kendo Web UI Grid里时间格式转换
  14. &lt; meta http-equiv = &quot;X-UA-Compatible&quot; content = &quot;IE=edge,chrome=1&quot; /&gt;的作用
  15. log4net配置文件
  16. Sunday串匹配算法 C语言实现
  17. select option 选中 取消js
  18. Excel制作考勤管理
  19. 牛客练习赛15A-吉姆的运算式(Python正则表达式瞎搞)
  20. Fusion 360教程合集27部

热门文章

  1. Redis:redis.conf配置文件 - 及配置详解
  2. 解决mount.nfs: access denied by server while mounting
  3. mysql大量数据分页查询优化-延迟关联
  4. 利用 FilesystemIterator 获取指定目录下的所有文件
  5. F5 Http monitor
  6. python chrome
  7. python 列表指导式
  8. WIN7 32运行提示无法定位api-ms-win-crt-heap-l1-1-0.dll解决方法
  9. 构造函数 析构函数的区别与联系 C#
  10. mac设置终端命令行别名alias(git、npm)