Yo uso AnimationTimer para varias tareas como la animación con el cambio de imágenes y ProgressIndicator de animación. Para lograr la necesaria velocidad puedo poner hilo a dormir, pero cuando varias animaciones se ejecutan simultáneamente se afectan entre otros a la velocidad. ¿Hay alguna otra manera para cambiar la velocidad de AnimationTimer? Ejemplo de código:

private void initialize() {
 programButtonAnimation=new AnimationTimer(){
            @Override
            public void handle(long now) {
                    showClockAnimation();
            }
        };
 programButtonAnimation.start();
}

private void showClockAnimation(){
    String imageName = "%s_"+"%05d"+".%s";
    String picturePath="t093760/diploma/view/styles/images/pink_frames/"+String.format( imageName,"pink" ,frameCount,"png");
    programButton.setStyle("-fx-background-image:url('"+picturePath+"')");
    frameCount++;
    try {
        Thread.sleep(28);
    } catch (InterruptedException e) {
        //TODO Auto-generated catch block
        e.printStackTrace();
    }
    if(frameCount>=120){
        programButtonAnimation.stop();
        frameCount=0;
    }
}
InformationsquelleAutor Alyona | 2015-05-10

3 Comentarios

  1. 6

    La AnimationTimer‘s handle método se invoca una vez para cada trama que se representa, en el FX Subproceso de Aplicación. Nunca se debe bloquear ese hilo, así que no te llame Thread.sleep(...) aquí.

    El parámetro pasado a la handle(...) método es una marca de tiempo, en nanosegundos. Así que si quieres acelerador actualizaciones para que no ocurra más de una vez, decir 28 milisegundos, usted puede usar esto para hacerlo:

    private void initialize() {
     programButtonAnimation=new AnimationTimer(){
    
                private long lastUpdate = 0 ;
                @Override
                public void handle(long now) {
                        if (now - lastUpdate >= 28_000_000) {
                            showClockAnimation();
                            lastUpdate = now ;
                        }
                }
            };
     programButtonAnimation.start();
    }
    
    private void showClockAnimation(){
        String imageName = "%s_"+"%05d"+".%s";
        String picturePath="t093760/diploma/view/styles/images/pink_frames/"+String.format( imageName,"pink" ,frameCount,"png");
        programButton.setStyle("-fx-background-image:url('"+picturePath+"')");
        frameCount++;
        if(frameCount>=120){
            programButtonAnimation.stop();
            frameCount=0;
        }
    }
    • Para obtener más ideas sobre el uso de AnimationTimer, recomiendo la lectura de este y este
    • Si handle se llama a una tasa fija, digamos cada 16ms o así, no de esta técnica de introducir jitter haciendo actualizaciones en 16, 32, 16, 16, 32ms, y así sucesivamente?
    • Sí, en este caso va a afectar la suavidad (ligeramente). Los enlaces en mi comentario anterior discutir las posibles soluciones a esta en un gran nivel de detalle. Realmente no es claro por qué el OP quiere estrangular a este más allá de la «natural» marco de representación de la tasa de JavaFX kit de herramientas de todos modos.
    • Lo siento, pero no veo la manera de los enlaces de abordar esta cuestión. Es un problema importante para Java que, AFAIK, en realidad no permitir un auténtico vsync. Otros han dicho que AnimationTimer proporciona vsync, pero mis experimentos refutar fácilmente. Asimismo page-flipping (lo que ayuda a evitar que se rompa) es otra solución ampliamente propone como un camino para lograr el vsync. Se concede, el OP fue después de algo más, pero muchos de estos problemas se reducen a no ser capaz de sincronización de bloqueo para la actualización. ¿Conoce usted a un camino?
    • El «aliasing temporal» de la técnica la técnica que me estaba refiriendo, que proporciona un mecanismo para suavizar los cambios solicitados entre los fotogramas. Pero en general es correcto que JavaFX no está diseñado para el bajo nivel de animación que describe (el principal caso de uso para JavaFX es de escritorio de aplicaciones de negocios, por lo que la API es realmente diseñado en torno a lo que es fácil para el diseño de la interfaz de usuario de control basado en las aplicaciones, comunicarse con los servicios, etc). La guía de la representación; el programador simplemente proporciona qué mostrar y permite que el kit de herramientas de hacer su trabajo.
    • Así que si usted está buscando para hacer de gama alta de animación que requiere el control sobre el actual proceso de representación, JavaFX (y probablemente de Java en general) no es probablemente el mejor conjunto de herramientas a utilizar. Es simplemente no está diseñado como un caso de uso principal en la mente.
    • Lo que estoy buscando es una manera de bloquear hasta el próximo vsync, así que puedo sincronizar mi representación con la tasa de actualización. Que, afaik, es la única manera de superar temporal aliasing (bonita frase, por cierto, mucho más elegante que «janking»). En Windows, DirectDraw había un WaitForVerticalBlank método, pero que de ahora en desuso. Aún no has descubierto si Direct2D/3D ofrece nada comparable.
    • Sí, simplemente no hay API para que en JavaFX. Creo que es sustancialmente diferente de la cuestión publicado aquí, así que probablemente este no sea el lugar adecuado para esta discusión. Pero la línea de fondo es que JavaFX no proporciona enlaces en el primitivo sistema de gráficos en ese nivel. El AnimationTimer permite ejecutar código en cada «pulso», pero el control de la generación de pulsos es – deliberadamente – enterrado en un impenetrable de la caja negra.

  2. 3

    Desde ya escribí el código y James_D fue más rápido con informar a usted acerca de que el bloqueo de la interfaz de usuario, todavía me gustaría añadir que si usted tiene múltiples AnimationTimers de tiempos diferentes, usted debe crear una clase dedicada para eso. Si cada uno de ellos se ejecuta a una velocidad diferente, se podría implementar como que:

    import javafx.animation.AnimationTimer;
    
    public abstract class AnimationTimerExt extends AnimationTimer {
    
        private long sleepNs = 0;
    
        long prevTime = 0;
    
        public AnimationTimerExt( long sleepMs) {
            this.sleepNs = sleepMs * 1_000_000;
        }
    
        @Override
        public void handle(long now) {
    
             //some delay
            if ((now - prevTime) < sleepNs) {
                return;
            }
    
            prevTime = now;
    
            handle();
        }
    
        public abstract void handle();
    
    }

    Lo que significa que el mango() método que se invoca al menos después de sleepMs milisegundos que han pasado.

    O cambiar el parámetro y especificar los fps, lo que usted necesita.

    Usted puede utilizar el código como este:

    AnimationTimerExt timer = new AnimationTimerExt(100) {
    
        @Override
        public void handle() {
    
            System.out.println( System.currentTimeMillis());
    
        }
    };
    
    timer.start();

    También, la carga de la imagen una y otra vez no es la mejor opción. Si quieres hacer animaciones, le sugiero que eche un vistazo a Mike Blog sobre La creación de un Sprite de Animación con JavaFX.

  3. 0
    new AnimationTimer() {
    int frameCount = 0;
            @Override
            public void handle(long currentNanoTime) {
    
                if (frameCount % 2 == 0) {
                 //30 fps ?
               }         
               frameCount++;
    }

    podría ser un poco chapucero, pero hace el trabajo

Dejar respuesta

Please enter your comment!
Please enter your name here