Qt QML:等待动画完成
我试图使可视动画连续。我有一个javascript函数,它调用myModel.move()两次。我有一个网格视图来显示我的模型,我有“x上的行为”动画,因此我可以直观地看到运动。但是,两个动作动画并行运行(它们之间的小延迟不明显) 我的想法是添加一个计数器,显示有多少动画已经开始,有多少动画已经完成。像这样的东西Qt QML:等待动画完成,qt,qml,Qt,Qml,我试图使可视动画连续。我有一个javascript函数,它调用myModel.move()两次。我有一个网格视图来显示我的模型,我有“x上的行为”动画,因此我可以直观地看到运动。但是,两个动作动画并行运行(它们之间的小延迟不明显) 我的想法是添加一个计数器,显示有多少动画已经开始,有多少动画已经完成。像这样的东西 Behavior on x { NumberAnimation { id: animationX; duration: 500;
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(...)
}
}
问题就在这里。我可以看到,在第一次移动()之后,所有必要的动画都开始了,但是什么也看不见,也没有一个动画完成。我有点僵持。如何解决这个问题
function doSomething() {
myModel.move(...)
while (myModel.busy) {}
myModel.move(...)
}
我不擅长javascript。但是你为什么要忙呢?我将创建两个函数
- 第一个是创建
,然后为将来的事件准备字段(比如创建一个将被单击的隐藏按钮)myModel.move()
- 第二个将在创建future事件时调用。在上面的示例中,它将是
Onclick
onRunningChanged
是事件处理程序的定义。为什么不创建相同的,让我们称之为onModelIdle
like
...
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(...)
}
}
以下是一个基于#UmNyobe的答案的有效解决方案。好的,QML是一种声明性语言,因此对于迭代问题是有问题的。欢迎提出任何意见。也许,有人可以建议更好(更可读)的纯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()
}
}
}
}
}
}
}
导入QtQuick 1.1
网格视图{
id:主栅格
单元宽度:165;单元高度:95
宽度:5*cellWidth;高度:4*cellHeight
型号:myModel
代表:我的按钮
属性字符串动画:“否”
属性int忙:0
信号总线
信号总线
onBusyPlus:{
忙碌的++
}
onBusyMinus:{
忙碌的--
if(busy==0)mainGrid.model.algorithm()
}
列表模型{
id:myModel
属性int步骤:0
属性1:0
函数createModel(){
对于(var i=1;iYes,我知道…简化的问题会产生简化的答案:-(事实上,我希望有许多不同的连续myModel.move(…)调用。但是,您的建议是可用的(请参阅我在下面发布的解决方案)。如果您想保持性能,繁忙的循环不是一个好主意。@UmNyobe Nowhere,为未来的绊脚石添加。}我可以补充一点,在浏览器中,您可以使用requestAnimationFrame创建具有图形性能的循环。Qt Quick还有一个等效版本的函数,当明智地使用该函数创建循环时,将提高图形动画的性能:非图形线程中的忙循环对于像pos一样快速处理数字来说是非常好的sible(而不是像处理requestAnimationFrame那样将循环限制为16毫秒刻度)。因此,这取决于用例。:)