2012-06-25 11 views
5

Meine Szene besteht nur aus einer ImageView, die ein Bild anzeigt. Ich möchte das Bild auf schwarz (zugewiesene Farbe der Szene) verblassen, und dann nach einiger Zeit wieder von Schwarz auf das Bild verblassen. Ich fand die FadeTransition sehr passend für diesen Zweck. Dies ist ein Stück von meinem Code:Wie man auf einen Übergang wartet, um in javafx 2.1 zu enden?

// 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(); 

Mein Problem ist, dass ft1.play() asynchron ist, so unter dem Code wird ausgeführt starten, bevor ft1.play() verlassen wird. Als Ergebnis sehe ich nur den zweiten Übergang. Wie kann ich warten, bis der erste Übergang beendet ist und dann den zweiten Übergang starten? Ich kann den Thread dazwischen nicht schlafen legen, weil es der Haupt-Javafx-Thread ist (versucht und nicht funktioniert).

Ich versuchte mit der onFinishedProperty() -Methode mit der Kombination von einem busy-Warten auf eine Flagge, aber ich bleibe für immer in der While-Schleife stecken. Hier ist mein Code dafür:

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(); 

Wie wird das Warten richtig gemacht? Danke

Antwort

3

Besetzt Warte (oder sogar Thread.sleep) auf dem Gewinde JavaFX-Anwendung ist immer eine schlechte Idee - man den Faden binden, die die UI-Verarbeitung, so dass Ihre Übergänge Griffe sowie der Rest Ihrer Benutzeroberfläche werden nie aktualisiert. Dadurch wird die App-Benutzeroberfläche für die Dauer der Besetztzeiten effektiv eingefroren. Für eine reaktionsfähige Benutzeroberfläche müssen Sie Ihre Logik so schnell wie möglich im FX-Anwendungs-Thread ausführen und dann den Thread loslassen, damit der Rest des JavaFX-Systems mit der Verarbeitung fortfahren kann. Aus diesem Grund haben die Übergänge asynchrone Rückrufe - die, sobald Sie sich daran gewöhnt haben, eine ganz natürliche Art der Entwicklung sind.

Zusätzlich zu den Uluk-Lösungen (die großartig sind), können Sie auch die SequentialTransition-Klasse für die Handhabung bei der Durchführung von Übergängen in Sequenz betrachten. Beachten Sie Folgendes: Wenn Sie nach Abschluss der SequentialTransition eine Aktion ausführen möchten, müssen Sie der SequentialTransition noch einen onFinished-Handler hinzufügen, um zu diesem Zeitpunkt Maßnahmen zu ergreifen.

+0

Ich denke, dass ich dachte, dass da die Übergänge play() asynchron sind, sie auf einem anderen Thread als dem JavaFX-Anwendungsthread passieren. Deshalb dachte ich, ich könnte den Haupt-Thread warten lassen, bis die Übergänge ihr Ding beendet haben und dann wieder aufgenommen werden. Jetzt sehe ich, dass, wenn der Anwendungsthread schläft, die Übergänge auch nicht verarbeitet werden können, oder? Also ich denke, die SequentialTransition ist die klarste Lösung für meinen Fall. Danke dir und Ukuk beides. – dadox

17

Ok, wenn Ihr ft2 die reflektierende Animation von ft1 ist dann

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

tun und Sie nicht ft2. Wenn Sie noch ft2 nach ft1 zu spielen, dann

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

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

Ok, kennst du eine andere Art, ein bestimmtes Stück Code auszuführen, nachdem play() fertig ist, außer setOnFinished()? Ich würde gerne in der Lage sein, die Übergänge über meinen Code zu organisieren, anstatt die Logik um die Übergänge herum zu organisieren ... – dadox

+1

Leider ist es, wie du erwähnt hast, unbehaglich, den Haupt-Thread in den Schlaf-/Wartemodus zu setzen. Die gleiche Schwierigkeit wird beim Anzeigen des modalen (Bestätigungs) -Dialogs angezeigt. Aber die showAndWait (v2.2) -Methode wird die Lösung bieten, die nur für modale Stufen anwendbar ist. –

1

Ich hatte ein Problem, wo anderer Code einige Berechnungen machte und ich Animationen in der JavaFX-App ausführen wollte, aber anderen Code brauchte, um auf die Beendigung der Animation zu warten. Ich war nicht in der Lage, diesen anderen Code zu sagen, wenn Animation beendet ist, so habe ich Methode erstellt Animation, für die Wiedergabe und dann darauf warten zu beenden:

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

Es ist erforderlich, dass diese Methode nicht in Haupt JavaFX aufgerufen wird thread, sonst funktioniert es für mich.

Verwandte Themen