[英]JavaFX: Not in Application Thread only when updating a Label?
在過去的幾天中,我一直在嘗試JavaFX,FXML,任務和屬性。 我偶然發現了一種奇怪的行為,希望您能幫助我更好地了解正在發生的事情。
我有一個看起來像這樣的簡約GUI: GUI
如果單擊按鈕,將創建並啟動一個新任務。 此任務將增加一個Double屬性,並將新值寫入Label並在ProgressBar中進行設置。 任務代碼可在此處查看:
public class TestTask extends Task<Void>{
private final DoubleProperty doubleValue = new SimpleDoubleProperty();
@Override
protected Void call() throws Exception {
for(double i = 0.1; i <= 1; i = i+0.1 ) {
doubleValue.set(i);
Thread.sleep(1000);
}
return null;
}
public DoubleProperty test() {
return doubleValue;
}
}
FXML控制器的代碼如下:
public class FXMLDocumentController implements Initializable {
@FXML private Label label;
@FXML private Slider slider;
//Called when the Button is clicked
@FXML
private void handleButtonAction(ActionEvent event) {
TestTask task = new TestTask();
task.test().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
//Works without problems
slider.setValue(newValue.doubleValue());
//Throws an exception
label.setText("Value" + newValue.doubleValue());
});
new Thread(task).start();
}
}
如果我運行此代碼,則嘗試更新Label的嘗試將導致以下異常:java.lang.IllegalStateException:不在FX應用程序線程上;否則,將顯示以下異常。 currentThread =線程4。 滑塊的更新工作正常,並且不拋出任何異常。
閱讀有關SO的以下問題后:
我了解Label的更新失敗,因為我試圖在監聽器中執行UI更新,該更新是從TestTask線程而不是從FXApplication線程調用的。
我現在的問題是:為什么“滑塊更新”工作正常並且沒有引發異常? 更新是在偵聽器中進行的,因此是在TestTask線程中進行的。 這種嘗試是否也應該引發“不在FX應用程序線程上”異常?
在此先感謝您抽出寶貴的時間來幫助我。
在偵聽另一個線程上的屬性更改時更新一個線程上的屬性只是一種競爭條件 。 不要這樣
JavaFX系統不僅假定對UI的更新發生在單個線程上,而且還假定屬性的更新相同,無論它們是否綁定到UI元素。 不要依賴JavaFX系統來檢查所有競爭條件並為您正確報告和處理它們,因為它並非旨在這樣做。
你需要以這樣的方式,以防止這樣的條件編寫代碼 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.