Qt动画框架

来源:互联网 发布:linux系统使用 编辑:程序博客网 时间:2024/05/16 00:54

Qt5以后官方大力推介QtQuick,有个重要的原因在于qml可以方便地写出酷炫的动态页面,在Qt widgets中,Qt也提供了C++可以直接使用的动画框架。

Qt动画框架可以是独立的,也可以是状态机框架的一部分。动画框架的顶层基类为QAbstractAnimation,它包含了一些在框架中被普遍使用的基本功能;尤其是启动、停止和暂停动画功能,它也接收定时触发通知。其子类QVariantAnimation和QAnimationGroup是两个抽象基类,提供动画类的单动画(QVariantAnimation)和多动画(QAnimationGroup)接口,我们可以直接使用的动画类分别继承自这两个基类:

单动画:QPropertyAnimation,继承自QVariantAnimation。

多动画:QSequentialAnimation(串行动画)、QParallelAnimation(并行动画),继承自QAnimationGroup

Qt动画框架主要类的继承关系如下图:


Qt动画框架更多介绍请查看Qt帮助文档,很多博客也基本是Qt帮助文档的中文翻译版。。在此不啰嗦了 。下面从三个方面讨论Qt动画框架的具体的使用方法。

1.实现单个动画(QPropertyAnimation)

Qt动画框架的核心是动画属性,通过动态改变对象的属性使其具有动画效果,如设定动画属性为"geometry",并调用setKeyValueAt()以一定间隔动态地改变widgets的位置,这样就实现了widgets的动画效果,示例如下:

    animation =new QPropertyAnimation(ui->label,"geometry",this);    animation->setDuration(15000);    animation->setKeyValueAt(0, QRect(0, 0, 10, 0));    animation->setKeyValueAt(0.5, QRect(250, 250, 100, 30));    animation->setKeyValueAt(1, QRect(0, 0, 10, 0));    animation->setEasingCurve(QEasingCurve::OutBounce);

setDuration设定动画的全程时间,然后依次调用setKeyValueAt()来设定动画过程中的间隔状态。

其中参1表示步进,必须处于0-1之间;参2为具体的设定值大小,参2为QVariant类型,其值必须与操作的动画属性(此处是"geometry")匹配,所以这里用QRect来设定每个状态具体的值。

setEasingCurve()在Qt中叫做缓和曲线,提供动画过渡的效果,可以是Qt自带的效果也可以是自定义效果。如该处设定的效果为退出时遇到终点反弹并逐渐衰弱:



以下是在QEasingCurve类中找到的Qt自带效果:


更简单地,我们可以只控制动画的起始状态,如下:

QPushButton button("Animated Button");button.show();QPropertyAnimation animation(&button, "geometry");animation.setDuration(10000);animation.setStartValue(QRect(0, 0, 100, 30));animation.setEndValue(QRect(250, 250, 100, 30));animation.start();

setStartValue()和setEndValue()分别设定动画属性的起始值,从而简单地控制整个动画效果。


2.实现串行/并行动画组(QSequentialAnimation、QParallelAnimation)

一个应用程序常常包含不止一个动画,因此就有了动画组
QAnimationGroup 的子类(QSequentialAnimationGroup和QParallelAnimationGroup)是动画容器类,

因此多个动画可以被串行或者并行。顾名思义,串行动画就是多个动画顺序地执行,并行则为多个动画对象同步执行。

示例:

    QPushButton *button1 = new QPushButton("hello");    button1->show();    QPushButton *button2 = new QPushButton("world");    button2->show();
    //分别设定两个动画对象    QPropertyAnimation *anim1 = new QPropertyAnimation(button1, "geometry");    QPropertyAnimation *anim2 = new QPropertyAnimation(button2, "geometry");    anim1->setStartValue(QRect(0,0,100,100));    anim1->setEndValue(QRect(250,250,100,100));    anim1->setDuration(10000);    anim2->setStartValue(QRect(250,250,100,100));    anim2->setEndValue(QRect(0,0,100,100));    anim2->setDuration(10000);
    //设定并行动画组    QParallelAnimationGroup *group = new QParallelAnimationGroup;    group->addAnimation(anim1);//将动画1加入动画组    group->addAnimation(anim2);//将动画2加入动画组    group->start();

这段代码运行的效果就是两个button窗体从屏幕的两个方向同时相向而行,因此采用了并行动画组。串行动画组的使用与此类似。


3.动画框架与图形视图

如果需要操作没有申明动画属性的QObject对象中的值,即自定义动画属性,必须提供一个能进行修改的设置函数和一个获取值的访问函数,如下:

class MyGraphicsRectItem : public QObject, public QGraphicsRectItem{    Q_OBJECT    Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)};

而在Qt图形视图框架中,若想使用动画效果,操作动画属性,上述添加可读写的自定义属性是必须的,因为图形视图中的Item均无动画属性,因此上述代码声明了一个"geometry"的自定义属性作为要操作的动画属性,另外:

由于QGraphicsItem并不继承于QObject。一个好的解决办法是子类化一个你需要的图形项,同时子类也继承于QObject(多重继承)。使用这种方法,QPropertyAnimation类就能使用于QGraphicsItem中。所以上述代码中的子类分别继承自QObject和QGraphicsRectItem。

另一种可行性是只继承于QGraphicsWidget,因为QGraphicsWidget继承于QObject。


4.Qt动画应用实例:实现窗口抖动效果

void MainWindow::onShakeWindow(){    QPropertyAnimation *pAnimation = new QPropertyAnimation(this, "pos");    pAnimation->setDuration(500);    pAnimation->setLoopCount(2);    pAnimation->setKeyValueAt(0, QPoint(geometry().x() - 3, geometry().y() - 3));    pAnimation->setKeyValueAt(0.1, QPoint(geometry().x() + 6, geometry().y() + 6));    pAnimation->setKeyValueAt(0.2, QPoint(geometry().x() - 6, geometry().y() + 6));    pAnimation->setKeyValueAt(0.3, QPoint(geometry().x() + 6, geometry().y() - 6));    pAnimation->setKeyValueAt(0.4, QPoint(geometry().x() - 6, geometry().y() - 6));    pAnimation->setKeyValueAt(0.5, QPoint(geometry().x() + 6, geometry().y() + 6));    pAnimation->setKeyValueAt(0.6, QPoint(geometry().x() - 6, geometry().y() + 6));    pAnimation->setKeyValueAt(0.7, QPoint(geometry().x() + 6, geometry().y() - 6));    pAnimation->setKeyValueAt(0.8, QPoint(geometry().x() - 6, geometry().y() - 6));    pAnimation->setKeyValueAt(0.9, QPoint(geometry().x() + 6, geometry().y() + 6));    pAnimation->setKeyValueAt(1, QPoint(geometry().x() - 3, geometry().y() - 3));    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);}

Qt的动画框架已经比较完善和强大,在C++开发的界面中灵活应用可以提高软件的交互性,如果想更加简单地实现动态页面,实现更多酷炫的效果,还是推荐使用QML写页面,C++控制后端逻辑的方式,这也是Qt官方目前主推的开发思路。



0 0