3

現在有人說它不適合使用Platform.runLater()從非JavaFX線程和Oracle站點更新UI引入綁定進度條更新的方式。在這裏我想更新一個標籤,所以這樣編碼它:Javafx在沒有直接調用的情況下從線程更新UI Platform.runLater

Task task = new Task() { 
    @Override 
    protected Object call() throws Exception { 
     int i = 0; 
     while (true) { 
      this.updateMessage("Count " + i); 
      System.out.println(i); 
      // Thread.sleep(10); 
      i++; 
     } 
    } 
}; 

Thread t = new Thread(task); 
lbStatus.textProperty().bind(task.messageProperty()); 
t.start(); 

它的工作原理。

我想知道是否夠好或者有其他方法可以考慮? 謝謝。

+0

可能重複[Java UI在UI替代品上運行](http://stackoverflow.com/questions/27113633/java-fx-running-on-ui-alternatives) – javaHunter 2014-12-05 09:47:50

回答

2

我不認爲說它不適合使用Platform.runLater(...)從後臺線程更新UI。肯定有這種情況是正確的,如Task Javadocs所示。 javafx.concurrent API提供的是一個「更高級別」的接口,用於編寫多線程JavaFX應用程序時通常需要的功能。這個包中的類是由具有多線程編程專業知識的人編寫的,所以很可能他們已經解釋了普通程序員可能不知道的微妙之處。

舉個例子,雖然updateMessage最終最終以調用Platform.runLater(...)結束,但兩者並不完全等價。如果你試圖用天真的通話同樣的事情Platform.runLater(..)

// Don't do this! It will make the UI unresponsive: 
Task task = new Task() { 
    @Override 
    protected Object call() throws Exception { 
     int i = 0; 
     while (true) { 
      Platform.runLater(() -> lblStatus.textProperty().set("Count "+i)); 
      i++; 
     } 
     return null ; 
    } 
}; 
Thread t = new Thread(task); 

您的用戶界面將成爲(至少部分地)反應遲鈍。原因是你在FX應用程序線程上調度了很多Runnable,它沒有時間去完成它的常規工作(呈現UI,響應用戶輸入等)。仔細編寫updateMessage(...)的實現是爲了將調用「扼殺」到Platform.runLater(...)(它基本上將它們限制爲每幀渲染一個)。這段代碼實現起來有點棘手:在代碼示例中使用javafx.concurrent API意味着您不必自己實現它。

因此,必須始終在FX應用程序線程上對UI進行更改,並且通過Platform.runLater(...)來安排這些更改的安排方式。實際上你要麼直接調用它,要麼調用最終調用它的代碼。但是,將調用包裝爲Platform.runLater(...)的一些API方法以非常複雜的方式完成,當這些方法提供您需要的功能時,您應該更願意自己進行調用。

+0

感謝您的回覆。 是的你是對的。直接調用Platform.runLater()卡住了用戶界面。 「一些將方法調用到Platform.runLater(...)」的API方法。你的意思是像updateMessage()這樣的方法嗎? 談到這個微粒代碼,這是否足夠好,還是有其他方法可以考慮? – 2014-12-05 17:56:02

+1

是的,'update *(...)'方法特別調用了UI;根據您的喜好經常調用這些方法基本安全。 – 2014-12-05 18:21:34

+0

另請參閱http://stackoverflow.com/questions/23488280/throttling-javafx-gui-updates – 2014-12-05 18:40:22

0

由於任務上的updateMessage()最終使用Platform.runLater()來更新messageProperty,所​​以它是代碼中的直接runLater()的替代方案。所以其實質是:

JavaFX不是多線程的,任何Porperty綁定只有在JavaFX線程中修改了屬性時纔會起作用。通過使用Platform.runLater()。

+0

謝謝你的回覆。 好的,但是當我們使用直接platform.runlater()它會導致完全掛起UI,當我們使用updateMessage()與一些綁定它工作正常。可能這就是爲什麼oracle使用綁定​​進行併發演示的原因。 https://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm。 現在的問題是... 我想知道這是否足夠好或有其他方法可以考慮? – 2014-12-05 17:50:10

+0

系統何時掛起,如果在上面的示例中調用了Platform.runLater(),而沒有在循環中調用Thread.sleep()?這將因以下原因而掛起:導致排隊的'runLater()'任務超載! – 2014-12-05 17:57:16

+0

是的,不調用Thread.sleep()。 使用綁定和updateMessage()時,即使循環內沒有線程休眠,也不會掛起。 – 2014-12-05 18:00:59

相關問題