![](/img/trans.png)
[英]java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
[英]Multithreading with JavaFX causes java.lang.IllegalStateException: Not on FX application thread
因此,我得到了一個相當簡單的JavaFX應用程序,該應用程序在按下開始按鈕時會創建並啟動2個線程。 我還有一個重置按鈕,該按鈕應該中斷線程並清除GUI組件。 這似乎很好。 然后,我應該能夠按下重置按鈕,然后再次按下啟動按鈕來創建2個線程,然后再次啟動它們。 這也有效。 當這些線程執行時,它們正在使用我的回調,將字符串還給我的Controller類,然后將其添加到列表視圖中。 第一次運行應用程序時,此方法運行良好,但是如果我按清除然后啟動,則在將數據添加到列表視圖時,回調會引發錯誤。 java.lang.IllegalStateException: Not on FX application thread
據我了解,每當main以外的其他線程嘗試更改fx元素時,都會引發此錯誤。 但是,為什么我第一次單擊“開始”而不是單擊“清除”然后重新開始后,它仍能正常工作? 這是我的代碼:
/**
* Controls GUI and start threads..
*
*
*/
public class Controller implements Initializable {
@FXML
private Button btnRun;
@FXML
private Button btnReset;
@FXML
private TextArea taInput;
@FXML
private ListView<String> lwProducer;
@FXML
private ListView<String> lwConsumer;
private boolean sync;
private Buffer buffer;
private ObservableList<String> conData;
private ObservableList<String> proData;
private Thread consumerThread;
private Thread producerThread;
private Runnable producerR;
private Runnable consumerR;
/**
* Initializes elements, sets an initial value for the textbox.
*/
public void initialize(URL location, ResourceBundle resources) {
taInput.setText("The quick brown\nfox jumps over\nthe lazy dog");
btnReset.setDisable(true);
btnRun.setDefaultButton(true);
lwProducer.setStyle("-fx-focus-color: transparent;");
lwConsumer.setStyle("-fx-focus-color: transparent;");
}
/**
* Eventhandler for btnRun that will start new threads.
*
* @param e
*/
@FXML
protected void btnRun(ActionEvent e) {
System.out.println(sync);
conData = FXCollections.observableArrayList();
proData = FXCollections.observableArrayList();
buffer = new Buffer();
producerR = new Producer(new ProducerCB(), buffer, taInput.getText());
consumerR = new Consumer(new ConsumerCB(), buffer);
producerThread = new Thread(producerR);
consumerThread = new Thread(consumerR);
producerThread.start();
consumerThread.start();
btnRun.setDisable(true);
taInput.setDisable(true);
btnReset.setDisable(false);
}
/**
* Eventhandler for btnReset. If pressed, threads and all gui components
* will be cleared.
*
* @param e
*/
@FXML
protected void btnReset(ActionEvent e) {
System.out.println("Resetting");
producerThread.interrupt();
consumerThread.interrupt();
producerThread = null;
consumerThread = null;
lwProducer.getItems().clear();
lwConsumer.getItems().clear();
conData = null
proData = null
producerR = null;
consumerR = null;
btnRun.setDisable(false);
taInput.setDisable(false);
btnReset.setDisable(true);
}
/**
* Callback for producer thread. Updates the left hand listview with added
* data.
*
*
*/
private class ProducerCB implements Callback {
@Override
public void returnData(String str) {
proData.add(str);
lwProducer.setItems(proData);
}
}
/**
* Callback for consumer thread. Updates the right hand listview with read
* data.
*
*/
private class ConsumerCB implements Callback {
@Override
public void returnData(String str) {
conData.add(str); // Throws exception!!!!!!!
lwConsumer.setItems(conData);
}
}
}
堆棧跟蹤
Exception in thread "Thread-7" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-7
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:236)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent$2.onProposedChange(Parent.java:367)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:575)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:204)
at com.sun.javafx.scene.control.skin.ListCellSkin.handleControlPropertyChanged(ListCellSkin.java:49)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(BehaviorSkinBase.java:197)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:103)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:144)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:49)
at javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at javafx.scene.control.Labeled.setText(Labeled.java:145)
at com.sun.javafx.scene.control.skin.ListViewSkin$2.updateItem(ListViewSkin.java:319)
at javafx.scene.control.ListCell.updateItem(ListCell.java:471)
at javafx.scene.control.ListCell.lambda$new$160(ListCell.java:167)
at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.util.AbstractList.add(AbstractList.java:108)
at assignment2.Controller.addData(Controller.java:163)
at assignment2.Controller.access$2(Controller.java:162)
at assignment2.Controller$ConsumerCB.returnData(Controller.java:158)
at assignment2.Consumer.run(Consumer.java:22)
at java.lang.Thread.run(Thread.java:745)
與AWT事件調度程序線程類似,僅在使用該Java FX應用程序線程時才可以更新JavaFx UI組件。
有關此主題的更多信息 ,請參見此處 。 解決此類問題的一種方法是使用Platform.runLater() 。
根據Stacktrace,您正在非fx線程中更改某些fx元素的值(稱為“ Thread-7”,顯然這是您創建的匿名線程)。我認為您可以在conData.add(str)和查看呼叫層次結構,您將找到自己的根本原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.