测试环境:win10、Qt Creator 4.11.1、5.14.2版本SDK

一、实际效果:

二、实现原理:

1.序列帧图是将一系列动作放在一张图中展示,一般每幅图大小相等(方便程序处理)。

2.根据每一帧大小定时绘制一幅图。

3.在paintEvent使用QPainter的drawPixmap进行绘制。

三、源代码

sequenceFrameAnimation.h#ifndef SEQUENCEFRAMEANIMATION_H
#define SEQUENCEFRAMEANIMATION_H#include <QWidget>
#include <QLabel>
#include <QTimer>
#include <QPixmap>class SequenceFrameAnimation : public QWidget
{Q_OBJECT
public:enum AnimationSequence{BeginToEnd,EndToBegin,};explicit SequenceFrameAnimation(QWidget *parent = nullptr);~SequenceFrameAnimation();bool setSequenceFrameAnimation(const QString& fileName, int frameWidth, int frameHeight, int frameRate);bool setAnimationSequence(AnimationSequence sequence);bool setStartFrameIndex(int index = 0);void setScaled(const QSize& size);    //设置缩放大小时,长宽必须是每一帧长宽的整数倍void setLoopEnabled(bool enabled);    //设置循环播放void setSpeedUpEnabled(bool enabled);    //动画启动加速过程bool start();    //开始void stop();    //结束signals:private slots:void onTimeout();void onSpeedUp();protected:void paintEvent(QPaintEvent *event) override;private:QPixmap m_sequenceFramePixmap;QSize m_scaledSize;QRect m_currentFrameRect;QTimer m_timer;QTimer m_speedUpTimer;const int m_maxSpeedUpCount;int m_currentSpeedUpCount;int m_perFrameWidth;int m_perFrameHeight;int m_frameRate;int m_frameIndex;int m_row;int m_col;AnimationSequence m_animationSequence;bool m_loop;bool m_needSpeedUp;private:int getCurrentSpeedUpTime();
};#endif // SEQUENCEFRAMEANIMATION_HsequenceFrameAnimation.cpp#include "sequenceframeanimation.h"
#include <QPainter>
#include <QStyleOption>
#include <QtMath>
#include <QDebug>#define SPEEDUP_INTERVAL 10SequenceFrameAnimation::SequenceFrameAnimation(QWidget *parent) : QWidget(parent),m_maxSpeedUpCount(10),m_currentSpeedUpCount(1),m_perFrameWidth(0),m_perFrameHeight(0),m_frameRate(0),m_frameIndex(0),m_animationSequence(BeginToEnd),m_loop(false),m_needSpeedUp(false)
{setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);setAttribute(Qt::WA_TranslucentBackground, true);connect(&m_timer, &QTimer::timeout, this, &SequenceFrameAnimation::onTimeout);connect(&m_speedUpTimer, &QTimer::timeout, this, &SequenceFrameAnimation::onSpeedUp);resize(100, 100);
}SequenceFrameAnimation::~SequenceFrameAnimation()
{}bool SequenceFrameAnimation::setSequenceFrameAnimation(const QString& fileName, int frameWidth, int frameHeight, int frameRate)
{bool ret = (fileName.isEmpty() ? false : true) && (frameWidth > 0) && (frameHeight > 0) && (frameRate > 0);if(ret){m_sequenceFramePixmap.load(fileName);m_col = m_sequenceFramePixmap.width() / frameWidth;m_row = m_sequenceFramePixmap.height() / frameHeight;m_perFrameWidth = frameWidth;m_perFrameHeight = frameHeight;m_frameRate = frameRate;m_currentFrameRect = QRect(0, 0, m_perFrameWidth, m_perFrameHeight);m_scaledSize = m_sequenceFramePixmap.size();resize(m_perFrameWidth, m_perFrameHeight);}return ret;
}bool SequenceFrameAnimation::setAnimationSequence(AnimationSequence sequence)
{bool ret = (BeginToEnd == sequence) || (EndToBegin == sequence);if(ret){m_animationSequence = sequence;}return ret;
}bool SequenceFrameAnimation::setStartFrameIndex(int index)
{bool ret = (0 <= index) && (index <= (m_row * m_col));if(ret){m_frameIndex = index;int x = 0;int y = 0;if(BeginToEnd == m_animationSequence){x = (m_frameIndex % m_col) * m_perFrameWidth;y = (m_frameIndex / m_col) * m_perFrameHeight;m_currentFrameRect = QRect(x, y, m_perFrameWidth, m_perFrameHeight);}else{x = m_sequenceFramePixmap.width() - (m_frameIndex % m_col + 1) * m_perFrameWidth;y = m_sequenceFramePixmap.height() - (m_frameIndex / m_col + 1) * m_perFrameHeight;m_currentFrameRect = QRect(x, y, m_perFrameWidth, m_perFrameHeight);}update();}return ret;
}void SequenceFrameAnimation::setScaled(const QSize& size)
{m_scaledSize = size;
}void SequenceFrameAnimation::setLoopEnabled(bool enabled)
{m_loop = enabled;
}void SequenceFrameAnimation::setSpeedUpEnabled(bool enabled)
{m_needSpeedUp = enabled;
}bool SequenceFrameAnimation::start()
{bool ret = m_sequenceFramePixmap.isNull() ? false : true;if(ret){m_sequenceFramePixmap = m_sequenceFramePixmap.scaled(m_scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);m_perFrameWidth = m_sequenceFramePixmap.width() / m_col;m_perFrameHeight = m_sequenceFramePixmap.height() / m_row;int x = 0;int y = 0;if(BeginToEnd == m_animationSequence){x = (m_frameIndex % m_col) * m_perFrameWidth;y = (m_frameIndex / m_col) * m_perFrameHeight;m_currentFrameRect = QRect(x, y, m_perFrameWidth, m_perFrameHeight);}else{x = m_sequenceFramePixmap.width() - (m_frameIndex % m_col + 1) * m_perFrameWidth;y = m_sequenceFramePixmap.height() - (m_frameIndex / m_col + 1) * m_perFrameHeight;m_currentFrameRect = QRect(x, y, m_perFrameWidth, m_perFrameHeight);}resize(m_perFrameWidth, m_perFrameHeight);if(m_needSpeedUp){m_currentSpeedUpCount = m_maxSpeedUpCount - 1;int time = getCurrentSpeedUpTime();m_speedUpTimer.setInterval(time);m_speedUpTimer.start();}else{m_speedUpTimer.start(m_frameRate);}update();}return ret;
}void SequenceFrameAnimation::stop()
{m_timer.stop();
}void SequenceFrameAnimation::onTimeout()
{m_frameIndex++;if(m_frameIndex >= (m_row * m_col)){if(m_loop){m_frameIndex = 0;}else{m_timer.stop();m_frameIndex = 0;return;}}int x = 0;int y = 0;if(BeginToEnd == m_animationSequence){x = (m_frameIndex % m_col) * m_perFrameWidth;y = (m_frameIndex / m_col) * m_perFrameHeight;}else{x = m_sequenceFramePixmap.width() - (m_frameIndex % m_col + 1) * m_perFrameWidth;y = m_sequenceFramePixmap.height() - (m_frameIndex / m_col + 1) * m_perFrameHeight;}m_currentFrameRect = QRect(x, y, m_perFrameWidth, m_perFrameHeight);update();
}void SequenceFrameAnimation::onSpeedUp()
{m_currentSpeedUpCount--;m_frameIndex++;m_frameIndex = m_frameIndex % (m_row * m_col);if(m_currentSpeedUpCount <= 0){m_speedUpTimer.stop();m_timer.start(m_frameRate);m_currentSpeedUpCount = m_maxSpeedUpCount;}else{int x = 0;int y = 0;if(BeginToEnd == m_animationSequence){x = (m_frameIndex % m_col) * m_perFrameWidth;y = (m_frameIndex / m_col) * m_perFrameHeight;}else{x = m_sequenceFramePixmap.width() - (m_frameIndex % m_col + 1) * m_perFrameWidth;y = m_sequenceFramePixmap.height() - (m_frameIndex / m_col + 1) * m_perFrameHeight;}m_currentFrameRect = QRect(x, y, m_perFrameWidth, m_perFrameHeight);int time = getCurrentSpeedUpTime();m_speedUpTimer.setInterval(time);update();}
}void SequenceFrameAnimation::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.setRenderHint(QPainter::SmoothPixmapTransform, true);painter.drawPixmap(rect(), m_sequenceFramePixmap, m_currentFrameRect);
}int SequenceFrameAnimation::getCurrentSpeedUpTime()
{return (m_frameRate + m_currentSpeedUpCount * SPEEDUP_INTERVAL);
}

四、使用示例

#include <QApplication>
#include "groupsucceedwidget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);SequenceFrameAnimation w1;w1.setSequenceFrameAnimation(":/images/voiceSequence.png", 243, 36, 200);   w1.setAnimationSequence(SequenceFrameAnimation::BeginToEnd);    //播放顺序:头到尾w1.setLoopEnabled(true);    //循环播放w1.show();w1.start();  return a.exec();
}

序列帧图:

Qt——功能:序列帧动画相关推荐

  1. Shader学习17——序列帧动画

    序列帧动画实际就是动态地去改UV点就行,实现的时候注意一下怎么取行列就可以 Mar-05-2021 15-16-55.gif c#代码里控制_Process的赋值,从1-行*列总数循环即可.测试的时候 ...

  2. NGUI_2.6.3_系列教程六(序列帧动画)

    今天我给大家讲一下如何使用NGUI做序列帧动画.本节主要包括两方面内容,分别是使用UIspirit和使用UITexture 做序列帧动画.废话不说了,下面开始. 还要在啰嗦一句,首先大家要准备一些序列 ...

  3. Unity序列帧动画疑难解答

    **Unity序列帧动画疑难解答 熟悉界面: 界面熟悉很重要,千万不要发生与别人沟通时你说菜单他去找工具栏的情况. **菜单栏:**基础创建设置工具等功能入口 **工具栏:**软件内的基本操作工具,基 ...

  4. Unity——用代码实现序列帧动画

    序列帧动画经常用到,最直接的方式就是用Animation录制.但某些情况下这种方式并不是太友好,需要靠代码的方式进行序列帧动画的实现. 代码实现序列帧动画,基本的思路是定义一个序列帧的数组/列表,根据 ...

  5. ❤️❤️❤️Unity废柴看过来,手把手教你做植物大战僵尸(二)—— 序列帧动画

    开始制作游戏,首先,我们要把游戏素材导入到项目中,我这里整理出来了一些项目中用到的图片音乐等素材,大家可以下载下来使用,或者自己从网上找其他好看的素材也可以. 植物大战僵尸素材 链接:https:// ...

  6. Unity shader入门精要学习笔记-代码篇6(序列帧动画/滚动背景/流动河流/广告牌/顶点动画的阴影)

    一.序列帧动画 建立一个四边形对着摄像机. 我们需要一张序列帧图像,这里用到8x8的爆炸图. 给四边形上材质和shader,代码如下: Shader "Custom/NewSurfaceSh ...

  7. Unity3D实现2D人物动画① UGUINative2D序列帧动画

    原理 看过前篇的朋友,一定能猜到这篇的内容了,2D人物动画,这是一个老生常谈的话题,很多人都写过或者提供过类似的代码,本文还是遵守着重原理,代码次之的原则.下面是根据以前自己学习的时候学习" ...

  8. 时光煮雨 Unity3D实现2D人物动画① UGUINative2D序列帧动画

    系列目录 [Unity3D基础]让物体动起来①--基于UGUI的鼠标点击移动 [Unity3D基础]让物体动起来②--UGUI鼠标点击逐帧移动 时光煮雨 Unity3D让物体动起来③-UGUI DoT ...

  9. Qt Creator制作动画

    Qt Creator制作动画 制作动画 创建时间表 将动画绑定到状态 管理关键帧 浏览时间轴 设置关键帧值 观看动画 编辑缓和曲线 将缓和曲线附加到关键帧 自定义缓和曲线 编辑动画曲线 旋转项目 制作 ...

  10. Unity Shader 序列帧动画

    shader中的序列帧动画属于纹理动画中的一种,主要原理是将给定的纹理进行等分,再根据时间的变化循环播放等分中的一部分. Unity Shader 内置时间变量 名称 类型 描述 _Time floa ...

最新文章

  1. RocketMQ NameServer启动要初始化哪些参数
  2. 中国三大轴承厂是 哪三家?
  3. python中的进程
  4. IE8,9下的ajax缓存问题
  5. HDU 3420 Bus Fair [补]
  6. 未解决:运行EtherCalc出错:Error: Cannot find module 'zappajs'
  7. 一个词三个功能,较真人员少啊
  8. win10安装CUDA和cuDNN
  9. PS画虚线的几种方法
  10. VMWare虚拟机处理器数量与每个处理器内核数量概念,以及分配CPU资源详解
  11. 90后HTTP 的爱情故事
  12. easyUI右侧搜索面板下拉列表框样例
  13. pAdTy_2 构建连接网络和云的应用程序
  14. python语言排行_2019年6月编程语言排行榜:Python 排名飙升,三年内有望超越Java...
  15. 撸一串趣图,给晚上加班打个鸡血
  16. 阿里云 代码权限管理
  17. 三个你必须要记住的Pyinstaller打包命令——利用Python实现打包exe
  18. 云顶之弈服务器维护多长时间,云顶之弈手游维护到几点?最新维护时间介绍
  19. 如何处理调用位于anaconda中的python解释器时出现warning问题
  20. 记忆方法<一> 前言

热门文章

  1. thinkphp防sql注入,入侵
  2. The WebSocket session [0] has been closed and no method (apart from close()) may be called on a clos
  3. 但在家具研发设计方面仍依赖“舶来品”,
  4. java自定义模拟线程池
  5. mitmproxy工具
  6. 漫画:用户的嘴,骗人的鬼!
  7. oracle 创建超大表空间文件,不用担心表空间占用满了
  8. VS2019项目打包exe文件教程
  9. 计组与OS中的“透明“
  10. java操作es查询数据总量