动画框架

主要类关系图

Animation_00.png

QAbstractAnimation

动画框架基础由基类QAbstractAnimation以及它的两个子类QVariantAnimation,QAnimationGroup组成.QAbstractAnimation是所有动画的祖先.它包含了一些在框架中被普遍使用的基本功能;尤其是启动,停止和暂停动画功能,它也接收定时触发通知.

QPropertyAnimation

Qt动画框架更是提供了QPropertyAnimation类,该类继承自QVariantAnimation,用于对Qt属性的动画操作(Qt属性系统是Qt元对象系统的一部分).QPropertyAnimation类使用缓和曲线算法对属性进行插值演化操作.因此当你想使用动画改变一个值时,需要声明其为一个属性并且使该类继承自QObject.这给我们提供了很大的方便性,去动画操作现有的部件和其它的QObject对象.

QAnimationGroup

复杂动画可以通过构建QAbstractAnimation树形结构来构造.该树主要使用QAnimationGroup.QAnimationGroup类是一个包含其它动画类的容器类;同时QAnimationGroup类也是QAbstractAnimation类的子类,因此一个容器可以包含其它容器.

主要类介绍

名称 描述
QAbstractAnimation 所有动画类的基类
QAnimationGroup 动画容器的基类
QParallelAnimationGroup 并行动画容器
QSequentialAnimationGroup 串行动画容器
QPauseAnimation QSequentialAnimationGroup 的暂停
QVariantAnimation 动画类的基类
QPropertyAnimation QT属性动画
QEasingCurve 控制动画的缓和曲线类
QTimeLine 控制动画的事件轴类

QT属性动画

如上所述,QPropertyAnimation类能够使用插值来修改Qt属性值,正是该类用于改变动画属性值。选择Qt属性动画的主要原因,是因为我们可以很自由的去动画操作QT API中已经存在的类,尤其是拥有bounds、colors等属性的QWidget类(能被嵌入到QGraphicsView中的QWidget).例如:

QPushButton  button("Animated Button");
button.show();

QPropertyAnimation animation(&button,"gemetry");
animation.setDuration(10000);
animation.setStartValue(QRect(0,0,100,30));
animation.setEndValue(QRect(250,250,100,30));
animation.start();

上面的代码 在10秒内把button从左上角(0,0)位置移动到位置(250,250).上面的代码在起始位置和终止位置之间做了线性插值.当然也可以在开始位置和结束位置之间设置其他值,这样插值就会经过这些点.例如:

QPushButton  button("Animated Button");
button.show();
QPropertyAnimation animation(&button,"gemetry");
animation.setDuration(10000);

animation.setKeyValueAt(0.0,QRect(0,0,100,30));
animation.setKeyValueAt(0.8,QRect(250,250,100,30));
animation.setKeyValueAt(1.0,QRect(0,0,100,30));
animation.start();

上面的代码在8秒内把button从(0,0)移动到(250,250),然后在2秒内重新移回到(0,0)位置.这些点之间的移动是通过线性插值完成的.

动画和图形视图框架

我们也可以使用QPropertyAnimation来动画操作QGraphicsItem.然而QGraphicsItem并不继承于QObject,一个好的解决办法是子类化一个你需要的图形项,同时这个类也继承自QObject.通过这种方式,QPropertyAnimation类就能适用于QGraphicsItem.另一种办法是只继承于QGraphicsWidget,因为QGraphicsWidget继承于QObject.例如:

class Pixmap : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
    Q_PROPERTY(QPointF pos READ pos WRITE setPos)
    ...

注意:因为元对象系统的要求,必须要首先继承子QObject.

缓和曲线

QPropertyAnimation在起始和结束属性值之间进行插值操作.除了为动画添加更多关键值外,也可以使用缓和曲线.化合曲线描述了一种控制在0和1之间插值速度的功能.使用它能在不改变动画路径的基础上控制动画的速度.例如:

QPushButton button("Animated Button");
button.show();

QPropertyAnimation animation(&button, "geometry");
animation.setDuration(3000);
animation.setStartValue(QRect(0, 0, 100, 30));
animation.setEndValue(QRect(250, 250, 100, 30));
animation.setEasingCurve(QEasingCurve::OutBounce);
animation.start();

QEasingCurve中有大量的曲线可供选择使用,他们被定义为QEasingCurve::Type枚举.我们也可以自定义缓和曲线,然后用QEasingCurve注册即可.

动画分组

一个程序中经常包含有多个动画,例如你想同时移动多个图形项,或者你想一个接一个的移动他们.QAnimationGroup的子类(QSequentialAnimationGroup 和QParallelAnimationGroup)是其他动画的容器类,这些动画就可以并行或者串行执行.QAnimationGroup类就是一个例子,其不操作动画属性,但是它能周期性的获得定时通知,这使得它能把定时通知应用于它所包含的动画中,从而通过它所包含的动画进行进行控制。

并行动画例子:

QPushButton* bonnie = new QPushButton("Bonnie");
QPushButton* clyde= new QPushButton("clyde");
bonnie->show();
clyde->show();

QPropertyAnimation* anim1 = new QPropertyAnimation(bonnie,"geometry");
QPropertyAnimation* anim2 = new QPropertyAnimation(clyde,"geometry");

QParallelAnimationGroup* group = new QParallelAnimationGroup;
group->addAnimation(anim1);
group->addAnimation(anim2);

group->start();

串行动画例子:

QPushButton button("Animated Button");
button.show();

QPropertyAnimation anim1(&button, "geometry");
anim1.setDuration(3000);
anim1.setStartValue(QRect(0, 0, 100, 30));
anim1.setEndValue(QRect(500, 500, 100, 30));

QPropertyAnimation anim2(&button, "geometry");
anim2.setDuration(3000);
anim2.setStartValue(QRect(500, 500, 100, 30));
anim2.setEndValue(QRect(1000, 500, 100, 30));

QSequentialAnimationGroup group;
group.addAnimation(&anim1);
group.addAnimation(&anim2);
group.start();

因为动画容器类也是动画,所以可以将其加入到其他动画容器中,这样就可以构建出一个动画的树形结构.该树形结构描述了动画彼此之间的运行关系.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容