I am trying to make visible animations sequential. I have a javascript function, which call myModel.move() two times. I have a GridView to show myModel and I have "Behavior on x" animation, thus I can visualy see the movements. But, both movement animatons runs in paralell (the small delay between them is not noticeable).
My idea was to add a counter of how many animations was started and how many of them already finished. Something like this;
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
}
}
}
}
This works as expected. Then, I add a loop to my javascript function to wait until all the animations finished.
ListModel {
id: myModel
property int busy: 0
function doSomething() {
myModel.move(...)
while (myModel.busy) {}
myModel.move(...)
}
}
Here is the problem. I can see that after the first move() all neccessary animations started, but nothing can be seen and none of the animation finished. I have some kind of a deadlock. How to solve this?
function doSomething() {
myModel.move(...)
while (myModel.busy) {}
myModel.move(...)
}
I am not good with javascript. But why do you busy loop? I would create 2 functions.
myModel.move()
, then prepare the field for a future event (like creating a hidden button which will be clicked)Onclick
.It seems that onRunningChanged
is a definition of event handler. Why not creating the same , lets call it 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(...)
}
}
Here is a working solution based on the answer from #UmNyobe. Well, QML is a declarative language and thus problematic for iterative problems. Any comments are welcomed. Maybe, someone can suggest better (more readable) pure QML program which will produce the same effect.
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()
}
}
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With