Qt帮助文档翻译——The Animation Framework

 动画框架旨在为创建动画和平滑GUI提供一种简单的方法。通过动画Qt属性,框架为动画控件和其他QObject提供很大的自由。框架也可以用于Graphics View 框架。在动画框架中看到的一些概念也能在Qt Quick中看到,它提供了声明的方式定义动画。动画框架的大部分知识可以应用于Qt Quick。

在这个概述中,我们解释了它的架构基础。我们还展示了框架允许动画QObjects和图形项目的最常见技术的例子。

The Animation Architecture

 在本节,我们将介绍动画框架的架构以及如何动画Qt属性。下图展示了动画框架中最重要的类。

 动画框架基础由基类QAbstractAnimation以及它的两个子类QVariantAnimation和QAnimationGroup组成。QAbstractAnimation是所有动画的祖先。它实现了框架中动画所有公用的基础属性;尤其是启动,停止和暂停动画功能。它也接收时间变化通知。

动画框架进一步提供QPropertyAnimation类,它是继承自QVariantAnimation类并且实现Qt属性(Qt属性是Qt元对象系统的一部分)的动画。类使用缓动曲线对动画插值。所以当你想要动画一个值,你可以将它声明为一个属性并让你的类成为一个QObject。注意这让我们在动画已经存在的控件和其它QObject时有更多的自由度。

复杂动画可以通过建造一个QAbstractAnimation的树结构来构建。通过QAnimationGroup建造树,QAnimationGroup功能是作为其他动画的容器。注意组也是QAbstractAnimation的子类,所以组自己也可以包含其他组。

动画框架可以单独使用,但也被设计为状态机框架的一部分(有关Qt状态机的介绍,请参阅状态机框架)。状态机提供了一个可以播放动画的特殊状态。QState也可以在状态进入或退出时设置属性,当给定QPropertyAnimation时,这个特殊的动画状态将在这些值之间插入。稍后我们将更详细地讨论这个问题。

在后台,动画由全局计时器控制,它向正在播放的所有动画发送更新。

关于类在框架中的功能和角色的详细描述,请查阅它们的类描述。

Classes in the Animation Framework

这些类为创建简单和复杂动画提供框架。

QAbstractAnimation

所有动画基础

QAnimationGroup

动画组的抽象基类

QParallelAnimationGroup

并行动画组

QPauseAnimation

串行动画组的暂停

QPropertyAnimation

动画Qt属性

QSequentialAnimationGroup

串行动画组

QVariantAnimation

动画的基类

QEasingCurve

控制动画的缓动曲线

QTimeLine

控制动画的时间线

Animating Qt Properties

 像前面提到的,QPropertyAnimation类可以对Qt属性插值。通常这个类应该用于值的动画;事实上,它的超类QVariantAnimation有一个updateCurrentValue()的空实现,并且不会改变任何值,除非我们自己在valueChanged信号上改变它。

我们选择动画Qt属性的主要原因是它为我们提供了在Qt API中动画已经存在的类的自由。尤其是QWidget类(我们也可以在QGraphicsView中嵌入它)有它的边界,颜色等属性。让我们看一个小例子:

  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();

这个代码将移动button,在10秒内从屏幕的左上角到位置(250,250)。

上面的例子实现了从起始和结束值之间的线性插值。也可以设置位于起始和结束值之间的值。然后插值将会经过这些点:

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

  QPropertyAnimation animation(&button, "geometry");
  animation.setDuration(10000);

  animation.setKeyValueAt(0, QRect(0, 0, 100, 30));
  animation.setKeyValueAt(0.8, QRect(250, 250, 100, 30));
  animation.setKeyValueAt(1, QRect(0, 0, 100, 30));

  animation.start();

 在这个例子中,动画将在8秒内将按钮移动到(250,250)点,然后在剩余2秒内将它移回起始位置。这些点间的运动是线性插值的。

你也可以动画一个QObject未声明为Qt属性的值。唯一的要求是这个值有一个设置器。然后,您可以创建包含该值的类的子类,并声明一个使用该setter的属性。注意每个Qt属性要求获取器,所以如果没有定义的话你需要提供一个获取器。

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

 上面的代码例子中,我们子类QGraphicsRectItem并定义一个几何属性。现在即使QGraphicsRectItem没有提供几何属性,我们也可以动画控件几何。

关于Qt属性系统的一般介绍,参考它的概述。

Animations and the Graphics View Framework

 当你想要动画QGraphicsItem,你也可以使用QPropertiAnimation。然而,QGraphicsItem不是继承自QObject。一个好的解决方法是子类化你想要动画的图形单元。然后这个类也要继承QObject。这种方式下,QPropertyAnimation可以用于QGraphicsItem。下面的例子展示如何做。另一中方法是继承自QGraphicsWidget,它本就是QObject。

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

 像前面描述的,我们需要定义我们期望动画的属性。

注意QObject必须是第一个继承类因为元对象系统要求这样。

Easing Curves

 像前面提到的,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注册它。

Putting Animations Together

 一个应用通常包含不止一个动画。举个例子,你可能想要同时移动不止一个图形单元或者按顺序移动他们。

QAnimationGroup子类(QSequentialAnimationGroup和QParallelAnimationGroup)是其他动画的容器,这些动画可以串行也可以并行动画。QAnimationGroup是一个不动画属性的动画例子,但它会周期性地得到时间变化的通知。这使它能够将这些时间变化转发给它所包含的动画,从而控制什么时候播放动画。

让我们看一下同时使用QSequentialAnimationGroup和QParallelAnimationGroup的代码示例,从后者开始。

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

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

  QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "geometry");
  // Set up anim1

  QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "geometry");
  // Set up anim2

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

  group->start();

 一个并行组同时播放多个动画。调用它的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();

你肯定已经猜到了,QSequentialAnimationGroup按顺序播放它的动画。它在前一个动画完成后开始列表中的下一个动画。

因为动画组本身就是一个动画,所以您可以将它添加到另一个组中。通过这种方式,您可以构建一个动画的树结构,它指定动画何时相对于其他动画播放。

Animations and States

当使用状态机时,我们可以使用QSignalTransition或QEventTransition类将一个或多个动画关联到状态之间的转换。这些类都派生自QAbstractTransition,它定义了方便的addAnimation()函数,该函数允许在发生转换时附加一个或多个触发的动画。

我们还可以将属性与状态关联起来,而不是自己设置开始和结束值。下面是一个完整的QPushButton几何动画代码示例。

  QPushButton *button = new QPushButton("Animated Button");
  button->show();

  QStateMachine *machine = new QStateMachine;

  QState *state1 = new QState(machine);
  state1->assignProperty(button, "geometry", QRect(0, 0, 100, 30));
  machine->setInitialState(state1);

  QState *state2 = new QState(machine);
  state2->assignProperty(button, "geometry", QRect(250, 250, 100, 30));

  QSignalTransition *transition1 = state1->addTransition(button,
      SIGNAL(clicked()), state2);
  transition1->addAnimation(new QPropertyAnimation(button, "geometry"));

  QSignalTransition *transition2 = state2->addTransition(button,
      SIGNAL(clicked()), state1);
  transition2->addAnimation(new QPropertyAnimation(button, "geometry"));

  machine->start();

有关如何将状态机框架用于动画的更全面的示例,请参见状态示例(它位于examples/animation/states目录中)。

官方文档:https://doc.qt.io/qt-5/animation.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值