2012-06-25 31 views
5

我的場景僅包含ImageView,顯示圖像。我想將圖像淡化爲黑色(場景的指定顏色),然後一段時間後,再次從黑色淡出到圖像。我發現FadeTransition非常適合這個目的。這是一張我的代碼:如何等待在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(); 

我的問題是ft1.play()是異步的,所以退出ft1.play()之前,下面的代碼將開始執行。結果我只看到第二次轉變。我如何等待第一次過渡到結束,然後啓動第二次過渡?我不能讓線程在兩者之間休眠,因爲它是主要的javafx線程(嘗試過並且沒有工作)。

我嘗試使用onFinishedProperty()方法結合忙於等待的標誌,但我永久卡在while循環中。這是我的代碼:

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

等待如何正確完成?謝謝

回答

3

忙等待(甚至了Thread.sleep)JavaFX應用程序線程始終是一個糟糕的主意 - 你綁它處理UI處理讓你的過渡線,以及其他用戶界面,永遠不會更新 - 在忙碌的等待期間有效地凍結應用用戶界面。對於響應式用戶界面,您需要儘快在FX應用程序線程上運行邏輯,然後讓線程繼續運行,以便JavaFX系統的其餘部分可以繼續處理。這就是爲什麼轉換有異步回調 - 一旦你習慣了它們,這是一種非常自然的開發方式。

除了Uluk的解決方案(很棒)之外,您還可以查看SequentialTransition類,以便按順序執行轉換。請注意,如果您想在SequentialTransition完成後執行操作,那麼您仍然希望在SequentialTransition中添加onFinished處理程序以便在此時執行操作。

+0

我想我在想,因爲轉換play()是異步的,它們發生在另一個線程上,然後是JavaFX應用程序線程。這就是爲什麼我認爲我可以讓主線等待轉換完成他們的事情,然後恢復。現在我看到,如果應用程序線程正在休眠,那麼轉換也無法處理,對嗎? 所以我認爲SequentialTransition是我的案例的最清晰的解決方案。感謝你和Ukuk。 – dadox

17

好吧,如果你的ft2ft1反射動畫然後做

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

,而你沒有ft2。如果您還需要ft2ft1後打那麼

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

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

好吧,你知道play()之後執行給定的代碼的另一種方式,除了setOnFinished()嗎?我希望能夠組織我的代碼轉換,而不是圍繞轉換組織邏輯...... – dadox

+1

不幸的是,正如你所提到的,讓主線程進入睡眠/等待模式是不安的。顯示模態(確認)對話框窗口時會產生同樣的困難。但是showAndWait(v2.2)方法將提供解決方案,僅適用於模態階段。 –

1

我有問題,其他代碼正在做一些計算,我想在JavaFX應用程序中運行動畫,但需要讓其他代碼等待動畫完成。我無法告訴這個其他代碼時動畫結束,所以我創建方法用於播放動畫,然後等待它完成:

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

,要求該方法沒有在主JavaFX的調用線程,否則,它適用於我。