动画学习:<QPropertyAnimation>
头文件
#include <QPropertyAnimation>
主要的API
构造函数:
QPropertyAnimation *anim = new QPropertyAnimation(目标对象,"属性名")
目标对象:需要动画的控件
属性名(property):支持动画的属性(之后会介绍)
关键属性API
主要有:持续时间,起始值,结束值,缓动曲线
anim->setDuration(500); //持续时间;单位时500ms
anim->setStartValue(); //起始值;属性不同,参数结构会变
anim->setEndValue(); //结束值;属性不同,参数结构会变
anim->setEasingCurve(); //缓动曲线;参数是QEasingCurve中的枚举类型(后面会具体介绍)
动画控制API
anim->start(); //立即启动动画
anim->pause(); //暂停动画
anim->resume(); //回复动画
anim->stop(); //停止动画
内存管理API
自动释放内存(推荐)
anim->start(QAbstractAnimation::DeleteWhenStopped); //结束的时候自动停止
注意
只能又一个start函数,()当中的内容是模式选择
代码演示:
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->resize(800,600);
//创建一个按钮
QPushButton *btn1 = new QPushButton("透明度",this);
btn1->resize(100,50);
btn1->move(QPoint(350,275));
//给btn1加透明化属性,因为按钮本来是没有透明度这个属性的,因此需要借助QGraphicsOpacityEffect给按钮简介控制按钮的透明度
QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(btn1);
btn1->setGraphicsEffect(effect);
//创建一个动画项
QPropertyAnimation *anim = new QPropertyAnimation(effect,"opacity");//此时动画属性是透明度
//设置动画参数
anim->setDuration(1000);//持续时间1s
anim->setStartValue(0);//开始为0
anim->setEndValue(1);//结束为1 补充 透明度是从0~1
anim->setEasingCurve(QEasingCurve::Linear);//弹跳效果(到最后忽然显示出来)
//开始动画并设置自动释放动画
anim->start(QAbstractAnimation::DeleteWhenStopped);
}
MainWindow::~MainWindow()
{
delete ui;
}
现在我来说一下,需要补充的内容
补充
按钮本身是没有透明度属性的,因此我们需要一个变量间接控制它的透明度,这就要引入
#include GraphicsOpacityEffct //图形透明度效果头文件
使用方法:
先用对应类实例化一个effect(名字自定义)对象,用该对象间接控制按钮的透明度
间接控制的方法:
btn1->setGraphicsEffect(effect);
常见用的动画属性
1、opacity 控件透明度
2、geometry 控件的位置和大小
3、pos 控件的位置
5、size 控件的大小
6、background 控件的背景颜色
7、windowOpacity 窗口整体透明度
8、scale 缩放比例
上面我们演示了透明度属性的使用方法
接下来我们详细介绍说一下1,2,3
代码演示
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->resize(800,600);
//这里我们用一个顺序动画组sequentialanimationgroup,将动画打包成组,并逐个展示
QSequentialAnimationGroup *group = new QSequentialAnimationGroup;
//创建几个按钮
QPushButton *btn1 = new QPushButton("opacity",this);
btn1->resize(100,50);
btn1->move(350,50);
QPushButton *btn2= new QPushButton("geometry",this);
btn2->resize(100,50);
btn2->move(350,150);
QPushButton *btn3 = new QPushButton("pos",this);
btn3->resize(100,50);
btn3->move(350,250);
QPushButton *btn4 = new QPushButton("size",this);
btn4->resize(100,50);
btn4->move(350,350);
QPushButton *btn5 = new QPushButton("background",this);
btn5->resize(100,50);
btn5->move(350,450);
QPushButton *btn6 = new QPushButton("scale",this);
btn6->resize(100,50);
btn6->move(350,550);
//opacity 示例
//给btn1加透明度属性
QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(btn1);
btn1->setGraphicsEffect(effect);
//创建opacity属性动画
QPropertyAnimation *anim1 = new QPropertyAnimation(effect,"opacity");
//配置effect动画参数
anim1->setDuration(1000);
anim1->setStartValue(0);
anim1->setEndValue(1);
anim1->setEasingCurve(QEasingCurve::InOutQuad);
//开始动画,并设置模式
//anim1->start(QAbstractAnimation::DeleteWhenStopped);
//此处是将动画开始决定权交给了 动画组
//geometry 示例
//创建geometry属性动画
QPropertyAnimation *anim2 = new QPropertyAnimation(btn2,"geometry");
//配置geometry动画参数
anim2->setDuration(1000);
anim2->setStartValue(QRect(0,0,20,20));
anim2->setEndValue(QRect(350,150,100,50));
anim2->setEasingCurve(QEasingCurve::OutBounce);
//开始动画,并设置模式
//anim2->start(QAbstractAnimation::DeleteWhenStopped);
//pos 案例
//创建pos 属性动画
QPropertyAnimation *anim3 = new QPropertyAnimation(btn3,"pos");
//配置pos 动画参数
anim3->setDuration(1000);
anim3->setStartValue(QPoint(0,0));
anim3->setEndValue(QPoint(350,250));
anim3->setLoopCount(2);//设置循环模式
anim3->setEasingCurve(QEasingCurve::OutBack);
connect(anim3, &QPropertyAnimation::currentLoopChanged, [anim3](int loop)
{
if (loop % 2 == 0)
{
anim3->setDirection(QAbstractAnimation::Forward);
}
else
{
anim3->setDirection(QAbstractAnimation::Backward);
}
});
//这里目的是实现往返操作,但是有问题:无论是执行Backward还是Forword,现象都是一样的
//下面我将分析一下(我代码过程中出现的错误,我觉得这个错误可能会有人和我有一样的疑问,我将在博客中给大家分析)
//开始动画,并设置模式
//anim3->start(QAbstractAnimation::DeleteWhenStopped);
//将动画添加到顺序动画组中
group->addAnimation(anim1);
group->addAnimation(anim2);
group->addAnimation(anim3);
//动画组开始
group->start(QAbstractAnimation::DeleteWhenStopped);
}
MainWindow::~MainWindow()
{
delete ui;
}
问题解释
这里我向大家解释一下,为什么会下面这部分代码会往返失败的原因
cpp
connect(anim3, &QPropertyAnimation::currentLoopChanged, [anim3](int loop)
{
if (loop % 2 == 0)
{
anim3->setDirection(QAbstractAnimation::Forward);
}
else
{
anim3->setDirection(QAbstractAnimation::Backward);
}
});
问题处在动画组中,动画组有自己控制流程,在动画组中 无法更改子动画的方向,
动画组本身不限制子动画方向 ,但需确保子动画的 startValue
/endValue
和按钮位置正确对齐!
补充知识点
动画组
头文件:
#include <QParalallelAnimationGroup>
#include<QSequentialAnimationGroup>
动画组共有两种:
一种是
QParalallelAnimationGroup 并行动画组
特点:动画组中的动画成员 同时展示动画,并行动画组的动画总时长由最长组动画时长决定
另一种是
QSequentialAnimationGroup 顺序动画组
特点:动画组中的动画成员 逐个展示动画,顺序动画组的动画总时长由总动画时长决定
注意点:
动画组中,动画的生命周期由动画组决定,因此子动画开始的时候,最好不要配置DeleteWhenStopped模式,因为如果配置了该模式,子对象运行完被释放,再配置group的start就导致,动画异常