2012-06-25 16 views
5

La scena è composta solo da un ImageView, che mostra un'immagine. Vorrei sfumare l'immagine in nero (colore assegnato della scena), quindi, dopo un po 'di tempo, sfumare di nuovo dal nero all'immagine. Ho trovato il FadeTransition molto adatto a questo scopo. Questo è un pezzo del mio codice:Come aspettare che una transizione termini in javafx 2.1?

// fade to black transition 
    FadeTransition ft1 = new FadeTransition(Duration.millis(2000), myImageView); 
    ft1.setFromValue(1.0); 
    ft1.setToValue(0.0); 
    ft1.play(); 

    // fade from black transition 
    FadeTransition ft2 = new FadeTransition(Duration.millis(2000), myImageView); 
    ft2.setFromValue(0.0); 
    ft2.setToValue(1.0); 
    ft2.play(); 

mio problema è che ft1.play() è asincrona, in modo che il codice qui sotto comincerà ad essere eseguito prima ft1.play() si esce. Come risultato vedo solo la seconda transizione. Come posso aspettare che la prima transizione termini e poi avviare la seconda transizione? Non riesco a mettere il thread in pausa perché è il thread javafx principale (provato e non funzionante).

Ho provato a utilizzare il metodo onFinishedProperty() con la combinazione di un busy-waiting su una bandiera, ma mi blocco nel ciclo while per sempre. Ecco il mio codice per questo:

boolean isTransitionPlaying; 
    FadeTransition ft = new FadeTransition(Duration.millis(2000), iv); 
    ft.setFromValue(1.0); 
    ft.setToValue(0.0); 
    ft.onFinishedProperty().set(new EventHandler<ActionEvent>() { 
     @Override 
     public void handle(ActionEvent actionEvent) { 
      transitionPlaying = false; 
     } 
    }); 
    transitionPlaying = true; 
    ft.play(); 

    while (transitionPlaying == true) 
    { 
     // busy wait 
     System.out.println("still waiting..."); 
    } 

    FadeTransition ft2 = new FadeTransition(Duration.millis(2000), iv); 
    ft2.setFromValue(0.0); 
    ft2.setToValue(1.0); 
    ft2.play(); 

Come viene eseguita correttamente l'attesa? Grazie

risposta

3

occupato di attesa (o anche Thread.sleep) sul thread dell'applicazione JavaFX è sempre una cattiva idea - legare il filo che gestisce l'elaborazione dell'interfaccia utente in modo che le transizioni , così come il resto dell'interfaccia utente, non viene mai aggiornato, bloccando in modo efficace l'interfaccia utente dell'app per tutta la durata dell'attesa. Per un'interfaccia utente reattiva, è necessario eseguire la logica sul thread dell'applicazione FX il più rapidamente possibile, quindi lasciare che il thread vada in modo che il resto del sistema JavaFX possa procedere con l'elaborazione. Questo è il motivo per cui le transizioni hanno richiami asincroni - che, una volta che ci si abitua a loro, sono un modo molto naturale di sviluppo.

Oltre alle soluzioni Uluk (che sono eccezionali), è possibile anche consultare la classe SequentialTransition per la gestione dell'assistenza durante l'esecuzione delle transizioni in sequenza. Si noti che se si desidera eseguire un'azione dopo che SequentialTransition è stato completato, si vorrà comunque aggiungere un gestore onFinished a SequentialTransition per agire in quel momento.

+0

Credo che stavo pensando che dal momento che le transizioni play() sono asincrone, avvengono su un altro thread, quindi sul thread dell'applicazione JavaFX. Questo è il motivo per cui ho pensato che avrei potuto fare in modo che il filo principale aspettasse che le transizioni finissero e poi riprendessero. Ora vedo che se il thread dell'applicazione sta dormendo, anche le transizioni non possono essere elaborate, giusto? Quindi immagino che SequentialTransition sia la soluzione più chiara per il mio caso. Grazie a te e Ukuk entrambi. – dadox

17

Ok se il vostro ft2 è l'animazione riflettente di ft1 poi fare

ft1.setAutoReverse(true); 
ft1.setCycleCount(1); 
// Or 
// ft1.setCycleCount(Timeline.INDEFINITE); 
// to loop infinitely (blinking effect) until stop() 

e non si ft2. Se hai ancora bisogno ft2 a giocare dopo ft1 poi

ft1.setOnFinished(new EventHandler<ActionEvent>() { 

    @Override 
    public void handle(ActionEvent event) { 
     ft2.play(); 
    } 
}); 
+0

Ok, conosci un altro modo di eseguire un determinato pezzo di codice dopo che è passata la riproduzione() oltre a setOnFinished()? Mi piacerebbe essere in grado di organizzare le transizioni sul mio codice piuttosto che organizzare la logica attorno alle transizioni ... – dadox

+1

Sfortunatamente, come hai detto, è difficile mettere il filo principale nella modalità di sospensione/attesa. La stessa difficoltà viene sollevata durante la visualizzazione della finestra di dialogo modale (conferma). Ma il metodo showAndWait (v2.2) fornirà la soluzione, che è applicabile solo agli stadi modali. –

1

Ho avuto problemi in cui altri codici eseguivano calcoli e volevo eseguire Animazioni nell'app JavaFX, ma dovevo fare in modo che altro codice attendesse che l'animazione finisse. Non ero in grado di dire questo altro codice quando l'animazione è terminata, così ho creato il metodo per la riproduzione di animazione e quindi in attesa che finisca:

private synchronized void playAnimationAndWaitForFinish(final Animation animation) { 
    if (Platform.isFxApplicationThread()) { 
     throw new IllegalThreadStateException("Cannot be executed on main JavaFX thread"); 
    } 
    final Thread currentThread = Thread.currentThread(); 
    final EventHandler<ActionEvent> originalOnFinished = animation.getOnFinished(); 
    animation.setOnFinished(new EventHandler<ActionEvent>() { 

     @Override 
     public void handle(ActionEvent event) { 
      if (originalOnFinished != null) { 
       originalOnFinished.handle(event); 
      } 
      synchronized (currentThread) { 
       currentThread.notify(); 
      } 
     } 
    }); 
    Platform.runLater(new Runnable() { 

     @Override 
     public void run() { 
      animation.play(); 
     } 
    }); 
    synchronized (currentThread) { 
     try { 
      currentThread.wait(); 
     } catch (InterruptedException ex) { 
      //somebody interrupted me, OK 
     } 
    } 
} 

E 'necessario che questo metodo non viene richiamato in main JavaFX filo, altrimenti, funziona per me.

Problemi correlati