2012-09-07 19 views
5

Estoy tratando de hacer animaciones visibles secuenciales. Tengo una función de JavaScript, que llama myModel.move() dos veces. Tengo un GridView para mostrar myModel y tengo una animación de "Comportamiento en x", así puedo visualizar los movimientos. Pero, ambas animaciones de movimiento se ejecutan en paralelo (la pequeña demora entre ellas no se nota).QML: espere hasta que finalicen las animaciones

Mi idea era agregar un contador de cuántas animaciones se iniciaron y cuántas de ellas ya terminaron. Algo como esto;

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

Esto funciona como se esperaba. Luego, agrego un bucle a mi función javascript para esperar hasta que finalicen todas las animaciones.

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

Aquí está el problema. Puedo ver que después del primer movimiento() comenzaron todas las animaciones necesarias, pero no se puede ver nada y ninguna de las animaciones finalizó. Tengo algún tipo de punto muerto. ¿Cómo resolver esto?

Respuesta

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

No soy bueno con javascript. Pero ¿por qué estás ocupado? Yo crearía 2 funciones.

  • La primera de ellas hace myModel.move(), a continuación, preparar el terreno para un evento futuro (como la creación de un botón oculto que se hace clic)
  • El segundo se llama cuando se crea el evento futuro. Con el ejemplo anterior, será Onclick.

Parece que onRunningChanged es una definición de controlador de eventos. ¿Por qué no crear el mismo, vamos a llamarlo onModelIdle como

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

Sí, lo sé ... preguntas simplificadas producen respuestas simplificadas :-(De hecho, quiero tener muchos myModel.move consecutiva diferente (...) llamadas. Sin embargo, su sugerencia es utilizable (ver el solución que publiqué a continuación). – meolic

+0

Un bucle ocupado no es una buena idea si desea mantener el rendimiento. – trusktr

+0

@trusktr y ¿a dónde ve? Digo que es una buena idea? – UmNyobe

1

Aquí es una solución de trabajo basado en la respuesta de #UmNyobe. Bueno, QML es un lenguaje declarativo y, por lo tanto, problemático para problemas iterativos. Cualquier comentario es bienvenido Tal vez, alguien pueda sugerir un mejor (más legible) programa QML puro que producirá el mismo efecto.

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() 
         } 
        } 
       } 
      } 
     } 
    } 
} 
Cuestiones relacionadas