2012-09-07 13 views
5

Ich versuche, Animationen sequentiell sichtbar zu machen. Ich habe eine JavaScript-Funktion, die myModel.move() zweimal aufruft. Ich habe eine GridView, um myModel zu zeigen und ich habe "Behaviour on x" Animation, so kann ich die Bewegungen sehen. Aber, beide Bewegungs animatons laufen in paralell (die kleine Verzögerung zwischen ihnen ist nicht bemerkbar).QML: warte bis Animationen fertig

Meine Idee war es, einen Zähler hinzuzufügen, wie viele Animationen gestartet wurden und wie viele von ihnen bereits fertig sind. Etwas wie das;

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 
      } 
     } 
    } 
} 

Dies funktioniert wie erwartet. Dann füge ich meiner JavaScript-Funktion eine Schleife hinzu, um zu warten, bis alle Animationen beendet sind.

ListModel { 
    id: myModel 
    property int busy: 0 
    function doSomething() { 
     myModel.move(...) 
     while (myModel.busy) {} 
     myModel.move(...) 
    } 
} 

Hier ist das Problem. Ich kann sehen, dass nach dem ersten Zug() alle notwendigen Animationen gestartet wurden, aber nichts ist zu sehen und keine Animation ist beendet. Ich habe eine Art Deadlock. Wie löst man das?

Antwort

2
function doSomething() { 
    myModel.move(...) 
    while (myModel.busy) {} 
    myModel.move(...) 
} 

Ich bin nicht gut mit Javascript. Aber warum bist du beschäftigt? Ich würde 2 Funktionen erstellen.

  • Die erste myModel.move() macht, dann das Feld für ein zukünftiges Ereignis vorzubereiten (wie eine versteckte Schaltfläche zu schaffen, die angeklickt werden) wird aufgerufen
  • Die zweite, wenn die das Ereignis in der Zukunft erstellt wird. Im obigen Beispiel wird es Onclick sein.

Es scheint, dass onRunningChanged eine Definition von Event-Handler ist. Warum nicht das gleiche zu schaffen, nennen wir es onModelIdle wie

... 
    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(...) 
    } 
} 
+0

Ja, ich weiß ... vereinfachte Fragen produzieren vereinfachte Antworten :-(In der Tat, ich mag vielen verschiedenen aufeinanderfolgende myModel.move haben (...) nennt. Allerdings Ihr Vorschlag verwendbar ist (siehe Lösung, die ich unten bekanntgab) – meolic

+0

Eine beschäftigte Schleife ist keine gute Idee, wenn Sie Leistung beibehalten möchten. – trusktr

+0

@trusktr und wo sehen Sie, dass ich sage, dass es eine gute Idee ist? – UmNyobe

1

Hier ist eine Arbeitslösung auf die Antwort von #UmNyobe basiert. Nun, QML ist eine deklarative Sprache und somit problematisch für iterative Probleme. Alle Kommentare sind willkommen. Vielleicht kann jemand besseres (besser lesbares) reines QML-Programm vorschlagen, das den gleichen Effekt erzeugt.

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() 
         } 
        } 
       } 
      } 
     } 
    } 
} 
Verwandte Themen