QT中的动画机制

目录

 

一、qt框架中主要动画类

二、各个类的主要作用

三、关于窗体的透明属性

四、qt框架的动画的一些弊端


一、qt框架中主要动画类

  • QPropertyAnimation
  • QSequentialAnimationGroup
  • QParallelAnimationGroup

二、各个类的主要作用

1、QPropertyAnimation

该类为属性动画类,顾名思义,qt的动画是基于窗体的某个属性,对该属性进行相应的变化来使得窗体动起来。同时,在运用动画时必要的步骤便是为某个窗体绑定一种动画。

举个栗子,比如widget窗体的属性geometry,该属性用于控制窗体在屏幕上的显示位置,该属性有4个参数,分别为x,y,w,h。即窗体在屏幕上的(x,y)座标点以及窗体的初始化宽和高,当窗体的座标点发生变化,而宽,高不变时,即可看到平移的动画效果;当加入宽高元素变化时,例如宽高由0变化至窗体正常大小时,即可看到缩放的动画效果。

QPropertyAnimation* pScaleAnimation = new QPropertyAnimation(ui->widget, "geometry");
pScaleAnimation->setDuration(1000);
pScaleAnimation->setStartValue(QRect(1920 / 2, 1080 / 2, 0, 0));
pScaleAnimation->setEndValue(QRect(0, 0, 1920, 1080));
pScaleAnimation->setEasingCurve(QEasingCurve::InOutQuad);

以上代码实现了窗体的缩放动画,首先new一个属性动画类,并将widget绑定于该动画,且绑定属性为“geometry”;其次规定该动画的持续时间,单位为ms;然后规定动画的起始座标以及结束座标;最后为该动画选择一种运动类型,qt官方提供了很多种不同的插值曲线来简化动画的制作,例如加速、减速、弹跳等插值曲线,来让整个动画框架显得更加完善。具体可参考官方文档中描述来选择自己所需要的动画曲线,官方文档链接为:https://doc.qt.io/qt-5/qeasingcurve.html。

2、QSequentialAnimationGroup

该类为串行动画组。当我们不满足於单一的缩放、平移效果,想拥有类似于Android平台的动画特效时,便需要用到串行动画组,通过将各个属性动画加入到该串行动画组中,依据加入动画组中的先后顺序,便可以呈现出更为复杂而有趣的动画,例如缩放展开动画+平移动画+缩放消失动画整个流畅的过程。但要注意的是对于串行动画组来说,在同一时间,只能有一个窗体的动画在运行,因为其为“串行”。

QSequentialAnimationGroup* pScaleGroup = new QSequentialAnimationGroup(this);
pScaleGroup->addAnimation(pScaleAnimation1);
pScaleGroup->addAnimation(pScaleAnimation2);
pScaleGroup->addAnimation(pScaleAnimation3);

以上代码展示了如何将已定义好的属性动画加入到串行动画组中。

3、QParallelAnimationGroup

该类为并行动画组。很多时候我们想要的动画也并不是单一的同一时间只能看到一个窗体动来动去,我们希望能够像Android平台那样丰富而又绚丽的多窗体动画,那么这个时候就需要用到该类了。通过将属性动画或者甚至是串行动画组加入到并行动画组中,我们便可以得到更加复杂,且窗体不限的动画效果,这个时候,在同一时间,便可以有多个窗体进行动画的展示。

QParallelAnimationGroup* m_group;
m_group = new QParallelAnimationGroup(this);
m_group->addAnimation(pScaleGroup);

以上代码展示了如何将已定义好的串行动画组加入到并行动画组中。

4、动画的运行

那么以上的代码只是用来声明一个或多个复杂的动画,那么如何才能让动画真正动起来呢?那么就需要按照如下的方式进行调用,在下面的代码中还有对动画正向或者反向的设置,qt已经为我们封装了一个宏用于反向动画的播放,而不必我们再次实现反向动画的声明和座标的计算等麻烦事情。另外可以设置动画运行的次数,即反复播放的次数。通过start()函数来让动画实际动起来。

QParallelAnimationGroup* m_group;
m_group->setDirection(QAbstractAnimation::Forward);
m_group->setLoopCount(1);
m_group->start();

以上代码展示了如何让动画动起来。

三、关于窗体的透明属性

透明属性需要另外的类参与来设置。

QGraphicsOpacityEffect* pWidgetOpacity = new QGraphicsOpacityEffect(this);
pWidgetOpacity->setOpacity(1);
widget->setGraphicsEffect(pWidgetOpacity);
QPropertyAnimation* pOpacityAnimation = new QPropertyAnimation(pWidgetOpacity, "opacity");
pOpacityAnimation->setDuration(s_time * 1000);
pOpacityAnimation->setStartValue(1);
pOpacityAnimation->setEndValue(0);
pOpacityAnimation->setEasingCurve(QEasingCurve::Linear);

以上代码实现了对窗体的透明度的属性的绑定以及由不透明到透明的渐变动画。

四、qt框架的动画的一些弊端

虽然qt提供了这些动画类来简化动画的制作,但是对于桌面应用来讲,无法做到像Android平台一样的动画流畅度,其动画效果的流畅程度只能说一般,而且在加载部分图片资源到窗体上的时候,如果图片资源较大,则会导致App占用内存较高,动画播放卡顿的现象十分严重。且特别要吐槽一下每个动画都必须要绑定窗体,无法做到某个位置的全部窗体适配,这一点是十分不方便的,在编写项目过程中令人十分头疼。在一些性能较差的嵌入式端平台上,qt项目的内存占用率以及cpu占用率一度高居不下,这实在是很烦恼的一件事情。

另外,在动画中难免不了对一些座标进行计算以及控制,这些点都十分麻烦以及繁琐,最近也采用了状态机的方式来制作动画,有时间再对状态机机制进行一些汇总,个人用起来感觉利用状态机来制作类似Android的动画会比较简单方便,但是状态机的动画效果仍然有很多地方不方便。

 

 

发布了52 篇原创文章 · 获赞 6 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章