QML:等到动画完成
Posted
技术标签:
【中文标题】QML:等到动画完成【英文标题】:QML: wait until animations finished 【发布时间】:2012-09-07 12:36:48 【问题描述】:我正在尝试使可见的动画连续。我有一个 javascript 函数,它调用 myModel.move() 两次。我有一个 GridView 来显示 myModel,并且我有“x 上的行为”动画,因此我可以直观地看到这些动作。但是,两个运动动画都是并行运行的(它们之间的微小延迟并不明显)。
我的想法是添加一个计数器,记录有多少动画已经开始,有多少已经完成。像这样的东西;
Behavior on x
NumberAnimation
id: animationX;
duration: 500;
onRunningChanged:
if (animationX.running)
console.log("Animation start");
myModel.busy = myModel.busy + 1
else
console.log("Animation stop");
myModel.busy = myModel.busy - 1
这按预期工作。然后,我在我的 javascript 函数中添加一个循环,以等待所有动画完成。
ListModel
id: myModel
property int busy: 0
function doSomething()
myModel.move(...)
while (myModel.busy)
myModel.move(...)
这就是问题所在。我可以看到,在第一次 move() 之后,所有必要的动画都开始了,但是什么也看不到,也没有动画完成。我有某种僵局。如何解决?
【问题讨论】:
【参考方案1】:function doSomething()
myModel.move(...)
while (myModel.busy)
myModel.move(...)
我不擅长 javascript。但是你为什么忙循环呢?我会创建 2 个函数。
第一个创建myModel.move()
,然后为将来的事件准备字段(例如创建一个隐藏按钮,然后点击)
创建未来事件时将调用第二个。对于上面的示例,它将是 Onclick
。
看来onRunningChanged
是事件处理程序的定义。为什么不创建相同的,我们称之为onModelIdle
像
...
onRunningChanged:
if (animationX.running)
console.log("Animation start");
myModel.busy = myModel.busy + 1
else
console.log("Animation stop");
myModel.busy = myModel.busy - 1
if(myModel.busy == 0)
// don't know the code, but trigger the onModelIdle event which
// be handled below
...
ListModel
id: myModel
...
onModelIdle
myModel.move(...)
【讨论】:
是的,我知道......简化的问题会产生简化的答案:-(事实上,我希望有许多不同的连续 myModel.move(...) 调用。但是,您的建议是可用的(请参阅我在下面发布的解决方案)。 如果要保持性能,繁忙的循环不是一个好主意。 @UmNyobe Nowhere,因此为未来的绊脚石添加。 : 我可能会补充一点,在浏览器中,您可以使用 requestAnimationFrame 创建图形性能循环。 Qt Quick 也有一个等效版本的函数,当明智地使用它来创建循环将导致图形动画的更好性能:doc.qt.io/qt-5/… 非图形线程中的繁忙循环非常适合尽快处理数字(而不是像使用 requestAnimationFrame 那样将循环限制为 16ms 滴答声)。所以,这取决于用例。 :)【参考方案2】:这是一个基于#UmNyobe 回答的有效解决方案。好吧,QML 是一种声明性语言,因此对于迭代问题是有问题的。欢迎任何cmets。也许,有人可以提出更好(更易读)的纯 QML 程序,它会产生相同的效果。
import QtQuick 1.1
GridView
id: mainGrid
cellWidth: 165; cellHeight: 95
width: 5*cellWidth; height: 4*cellHeight
model: myModel
delegate: myButton
property string animate: "no"
property int busy: 0
signal busyPlus
signal busyMinus
onBusyPlus:
busy++
onBusyMinus:
busy--
if (busy == 0) mainGrid.model.algorithm()
ListModel
id: myModel
property int step: 0
property int one: 0
function createModel()
for (var i=1; i<=20; i++)
append("display": i)
function algorithm()
if (step == 0)
move(0,19,1)
one = 0
step++
else if (step == 1)
if (one < 19)
move(one,one+1,1)
one++
if (one == 19) step++
else if (step == 2)
move(0,1,1)
move(5,6,1)
move(10,11,1)
move(15,16,1)
step++
Component.onCompleted:
createModel()
mainGrid.animate = "yes"
algorithm()
Component
id: myButton
Item
id: item
width: mainGrid.cellWidth-5; height: mainGrid.cellHeight-5;
Rectangle
id: box
parent: mainGrid
x: item.x; y: item.y;
width: item.width; height: item.height;
border.width: 1
Text
anchors.centerIn: parent
text: display
font.pixelSize: 48
Behavior on x
enabled: mainGrid.animate == "yes"
NumberAnimation
id: animationX;
duration: 1000;
onRunningChanged:
if (animationX.running) mainGrid.busyPlus()
else mainGrid.busyMinus()
Behavior on y
enabled: mainGrid.animate == "yes"
NumberAnimation
id: animationY;
duration: 1000;
onRunningChanged:
if (animationY.running) mainGrid.busyPlus()
else mainGrid.busyMinus()
【讨论】:
以上是关于QML:等到动画完成的主要内容,如果未能解决你的问题,请参考以下文章