|  | 
 
| 
本帖最后由 miss陈 于 2017-4-16 22:59 编辑
x
马上注册,结交更多好友,享用更多功能^_^您需要 登录 才可以下载或查看,没有账号?立即注册  
 引言
 
 动画很让人烦恼,在Qt中,已经给出了很多简单的动画,例如 QPropertyAnimation 类实现的动画,但是还不够智能,不是我想要的,相信你也有同感,今天我们就来实现自定义动画类来方便我们日后的开发。
 
 版权所有:瓯裔,转载请注明出处:http://blog.csdn.net/csnd_ayo
 
 简介
 
 操作系统:window7 x64
 编程IDE:Qt Creator 4.2.1
 Qt版本: 5.0.3 · 5.3.0 · 5.8.0
 最后更新:2017年4月14日
 
 
 效果展示
 为了减小文件,我对gif动画做了一些删减,所以看起来好像有跳帧的现象,其实并没有。
 
 Qt动画实现效果展示图
 
 所需资源
 
 
 封装后引用
 
 封装后我只需要五行代码即可显示自定义的动画了。
 
 #include "widget.h"
 #include "ui_widget.h"
 #include "customdynamicwidget.h"
 Widget::Widget(QWidget *parent) :
 QWidget(parent),
 ui(new Ui::Widget)
 {
 ui->setupUi(this);
 dynamicAnima_ = new CustomDynamicWidget(this);
 dynamicAnima_->setAnimation(QPixmap(":/q/level_num.png"),10,100);
 dynamicAnima_->setGeometry(41,41,41,41);
 dynamicAnima_->show();
 // 顺时针播放每帧
 dynamicAnima_->startClockwise();
 
 }
 
 Widget::~Widget()
 {
 delete ui;
 }
 下载
 
 拥有了这个类,你就拥有了所有动画!
 
 代码:下载
 图片:下载
 
 原理
 
 实现关联
 #include <QTimer>
 #include <QPainter>
 #include <QWidget>
 逻辑流程
 
 等比例切割传入的图片元素
 
 创建定时器,并关联更新槽
 等比例对图片进行切割
 利用了定时器(QTimer) 定时更新界面
 
 定时器被触发
 辨别当前帧
 若是尾帧辨别是否启用了动画无限循环
 修改帧
 更新界面
 重写paintEvent函数,利用画家类(QPainter) 完成自绘。
 
 获取当前帧的对应图片
 更新当前窗口
 实现
 
 逻辑函数
 
 1、等比例切割传入的图片元素
 /*
 * 设置动画
 * setAnimation
 * _pix:图片
 * _count:图片帧数
 * _msec:切换速度 (毫秒 1秒 = 1000毫秒)
 */
 void CustomDynamicWidget::setAnimation(const QPixmap &_pix, const short _count, const int _msec) {
 count_ = _count;
 currentIndex_ = 0;
 
 if (!pixList_.empty()) {
 pixList_.clear();
 }
 else {
 /*  顺时针动画关联  */
 clockTimer_ = new QTimer(this);
 clockTimer_->setInterval(_msec);
 connect(clockTimer_, SIGNAL(timeout()), this, SLOT(updateClockwise()));
 
 /*  逆时针动画关联  */
 counterclockTimer_ = new QTimer(this);
 counterclockTimer_->setInterval(_msec);
 connect(counterclockTimer_, SIGNAL(timeout()), this, SLOT(updateCounterclockwise()));
 }
 
 /*  链式动画图标分离  */
 for(short i=0; i != _count; ++i) {
 pixList_.append(_pix.copy(i * (_pix.width() / _count), 0,
 _pix.width() / _count, _pix.height()));
 }
 
 currentPix_ = pixList_.at(0);
 this->setGeometry(0,0,currentPix_.width(),currentPix_.height());
 
 update();
 2、利用了定时器(QTimer) 定时更新界面
 void CustomDynamicWidget::updateClockwise(void) {
 do {
 if (currentIndex_ < count_ && currentIndex_ >= 0) {
 /*  更新帧  */
 currentPix_ = pixList_.at(currentIndex_);
 update();
 
 /*  判断帧数  */
 if (currentIndex_ >= (count_ - 1)) {
 if(isLoop_) {
 currentIndex_ = 0;
 return;
 }
 break;
 }
 
 /*  跳帧  */
 ++currentIndex_;
 return;
 }
 #ifndef QT_NO_DEBUG
 else {
 qDebug() << __FUNCTION__ << "waring: 错误的下标" << currentIndex_;
 }
 #endif
 } while(false);
 
 clockTimer_->stop();
 currentIndex_ = 0;
 emit clockwiseFinished();
 }
 
 3、重写paintEvent函数,利用画家类(QPainter) 完成自绘。
 void CustomDynamicWidget::paintEvent(QPaintEvent *) {
 QPainter painter(this);
 painter.drawPixmap(rect(), currentPix_);
 }
 头文件
 #ifndef CUSTOMDYNAMICWIDGET_H
 #define CUSTOMDYNAMICWIDGET_H
 
 /*
 * 自定义动画类
 * 作者:瓯裔
 * 邮箱:727057301@qq.com
 * CSDN:http://blog.csdn.net/csnd_ayo
 * 创建时间:2017年1月9日 19:34:13
 * QT版本:5.0.2 ~ 5.8.0
 */
 
 #include <QWidget>
 
 /*
 * 说明:
 *   当前类是针对一张链式图片
 *   链式图片默认为8帧,默认0.1秒播放一帧
 *   可以根据自己需要进行设置与更改
 *   进行自动切割,循环播放每一帧
 *
 * 示例:
 *   类内声明 CustomDynamicWidget* dynamicAnima_
 *   ui->setupUi(this);
 *   dynamicAnima_ = new CustomDynamicWidget(this);
 *   dynamicAnima_->setAnimation(QPixmap(":/res/loading.png"),8,100);
 *   dynamicAnima_->setGeometry(100,100,300,300);
 *   dynamicAnima_->show();
 *   // 顺时针播放每帧
 *   dynamicAnima_->startClockwise();
 */
 
 class QTimer;
 class CustomDynamicWidget : public QWidget
 {
 Q_OBJECT
 public:
 
 explicit CustomDynamicWidget(QWidget *parent = 0);
 /*
 * 设置动画图标
 * 函数名:setAnimation
 * 参数 _pix:图标实例
 * 参数 _count:图标实例动画帧数
 * 参数 _msec:动画切帧速度 (毫秒级)
 */
 void setAnimation(const QPixmap& _pix, const short _count = 8, const int _msec = 100);
 
 /*  开始动画(顺时针)  */
 void startClockwise(void);
 /*  开始动画(逆时针)  */
 void startCounterclockwise(void);
 /*  停止动画  */
 void stop(void);
 /*  设置动画无限循环  */
 void setLoop(const bool _isLoop = false) { isLoop_ = _isLoop; }
 
 signals:
 
 /*  顺时针动画结束  */
 void clockwiseFinished(void);
 /*  逆时针动画结束  */
 void counterclockwiseFinished(void);
 
 private slots:
 
 /*  顺时针动画槽  */
 void updateClockwise(void);
 /*  逆时针动画槽  */
 void updateCounterclockwise(void);
 
 protected:
 
 void paintEvent(QPaintEvent *);
 
 private:
 
 /*  动画(是否无限循环)  */
 bool isLoop_;
 /*  图标列表数量  */
 short count_;
 /*  当前展示的图标下标  */
 short currentIndex_;
 /*  控制顺时针槽定时器  */
 QTimer *clockTimer_;
 /*  控制逆时针槽定时器  */
 QTimer *counterclockTimer_;
 /*  当前展示的图标  */
 QPixmap currentPix_;
 /*  图标列表  */
 QList<QPixmap> pixList_;
 
 };
 
 #endif // CUSTOMDYNAMICWIDGET_H
 | 
 |