您的位置:首页 > 编程语言 > Qt开发

Qt:在QML中使用Animator,让动画无卡顿

2017-08-31 11:22 721 查看
之前有说如果使用Qt的PropertyAnimation做Material曲线动画。

传送门:
http://blog.csdn.net/wsj18808050/article/details/72869043


PropertyAnimation是Qt提供的属性动画,用的非常广泛。可以适用于很多场合,比如说X的移动,甚至自定义属性的修改。他还有很多派生类,比如说NumberAnimation、ColorAnimation,这里不一一展开。

但是Animation有一个遗憾,就是它运行在GUI线程。

为什么说这是一个遗憾,因为按照我们一般的开发情况,并不能充分利用异步API,或者某些操作就是卡顿(比如说QML代码编译),这些都会导致GUI线程无法正常刷新界面。这样我们的60FPS就没了。

比如一个操作,需要200MS,按照60FPS的16MS间隔,这样就掉了12帧,已经肉眼可以明显分辨了。如果这个动画是从左移动到右边这种动画,那么这个动画看上去会非常不舒服。

既然QML是一个专门做界面的语言,那么这种问题,Qt自然已经考虑了,并且对此提供了一个解决方案,就是Animator。介绍如下:

Animator types are different from normal Animation types. When using an Animator, the animation can be run in the render thread and the property value will jump to the end when the animation is complete.


其中我们需要关心的重点是

the animation can be run in the render thread


也就是说,动画可以运行在渲染线程,而非主线程。这就意味着动画可以不受主线程卡顿的影响,流畅的运行。

来一个示例:

import QtQuick 2.6
import QtQuick.Window 2.2

Window {
visible: true
width: 600
height: 400

Rectangle {
id: rectangle1
x: 50
y: 50
width: 100
height: 100
color: "#ff00ff"
}

Rectangle {
id: rectangle2
x: 50
y: 250
width: 100
height: 100
color: "#ff00ff"
}

NumberAnimation {
id: animation
target: rectangle1
property: "x"
from: 50
to: 450
duration: 1000
}

XAnimator {
id: animator
target: rectangle2
from: 50
to: 450
duration: 1000
}

Timer {
id: timer
interval: 100
repeat: true
running: animation.running

onTriggered: {
Helper.msleep( 50 );
}
}

MouseArea {
anchors.fill: parent

onClicked: {
animation.running = true;
animator.running = true;
timer.running = true;
}
}
}


在这个示例中,创建了两个紫色的Rectangle,并且在鼠标点击后,从左移动到右边。主要关注:

上面的Rectangle,使用NumberAnimation,指定property为x,进行动画

下面的Rectangle,使用XAnimator,进行动画

每100ms,会让gui线程休眠50ms,来模拟卡顿。

运行效果如下:



* CSDN我没找到哪里上传视频,这个gif录制出来差异就不明显了 *

从这里可以看出,上面的Rectangle,从左到右是一点点卡过去,毫无流畅可言。甚至因为卡顿,都没能在预设的时间内完成动画。

而下面的Rectangle从左到右,丝滑般流畅,无卡顿。

至此,我们通过简单的,将Animation替换为Animator,就解决了gui线程卡顿带来的界面卡顿问题。

但是,Animator不是万能的,也有局限,使用的时候务必注意:

Animator支持的类型很少,只有x、y、opacity、rotation、scale和uniform,不支持自定义类型

Animator依赖渲染线程,程序必须是多线程渲染模式才可以使用Animator,不然效果和普通的Animation一样。不过现在Quick程序一般都已经是多线程渲染了。

Animator不支持reversible

如果Animation和Animator混用,很有可能让动画播放上不一致(即使设置的时间是一样的),就是Animator负责的动画已经完成了,但是Animation的动画因为卡顿或其他原因,还在进行中。例如上面的那个示例。

总的说,Animator是一种优化手段,但是它并不能完全替代Animation,应该说是一个互相补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: