Exception in thread "Thread-5" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
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.LabelSkin.handleControlPropertyChanged(LabelSkin.java:49)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$70(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 edu.controller.GUIController.statusShow(GUIController.java:443)
at edu.controller.GUIController.lambda$7(GUIController.java:214)
at java.lang.Thread.run(Unknown Source)
我正在做一个文本编辑器,我想在页脚中添加一个状态栏,该状态栏会在几秒钟后告诉用户不同的提示,当我尝试在标签上设置文本但当我遇到这种错误时,我会遇到此错误尝试在工作正常的控制台上设置该文本。
new Thread(()->{
statusBarShow();
}).start();
private void statusBarShow(){
try {
statusLable.setText("Tip 1");
Thread.sleep(2000);
statusLable.setText("Tip 2");
Thread.sleep(2000);
statusLable.setText("Tip 3");
Thread.sleep(2000);
statusLable.setText("Tip 4");
Thread.sleep(2000);
statusLable.setText("Tip 5");
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
}
答案 0 :(得分:2)
唯一允许修改JavaFX GUI的线程是JavaFX线程。如果任何其他线程修改了UI,您将获得异常。
此常见问题的最简单答案是将更改GUI的代码包装在Platform.runLater()
中。注意不要在runlater()中放置任何睡眠,因为它们会导致JavaFX GUI线程睡眠,这将导致您的程序在睡眠期间冻结。
Platform.runLater()
具有以下javadoc:
在某些情况下在JavaFX Application Thread上运行指定的Runnable 未来未指定的时间。此方法可以从 任何线程,都会将Runnable发布到事件队列,然后返回 立即给呼叫者。 Runnables按顺序执行 他们被张贴。传递给runLater方法的runnable将是 在任何Runnable传递给后续调用之前执行 runLater。如果已在JavaFX运行时之后调用此方法 关闭时,调用将被忽略:Runnable将不会执行 不会抛出异常。
注意:应用程序应避免将太多未决的JavaFX淹没 Runnables。否则,应用程序可能无法响应。 鼓励应用程序将多个操作分批处理 runLater调用。此外,应执行长时间运行的操作 在可能的情况下在后台线程上释放JavaFX GUI操作的应用程序线程。
不得在FX运行时之前调用此方法 初始化。对于扩展应用程序的标准JavaFX应用程序, 并使用Java启动器或其中的一种启动方法 应用程序类来启动应用程序,FX运行时是 在加载Application类之前由启动程序初始化。 对于使用JFXPanel显示FX内容的Swing应用程序,FX 当第一个JFXPanel实例为 建造。对于使用FXCanvas显示FX的SWT应用程序 内容,在第一个FXCanvas初始化FX运行时 实例已构建。
我认为您的代码不是以最佳方式完成此任务的,但以下是一个非常简单的解决方案:
new Thread(()->{
statusBarShow();
}).start();
private void statusBarShow(){
try {
Platform.runLater(()->statusLable.setText("Tip 1"));
Thread.sleep(2000);
Platform.runLater(statusLable.setText("Tip 2"));
Thread.sleep(2000);
Platform.runLater(statusLable.setText("Tip 3"));
Thread.sleep(2000);
Platform.runLater(statusLable.setText("Tip 4"));
Thread.sleep(2000);
Platform.runLater(statusLable.setText("Tip 5"));
} catch (Exception e) {
e.printStackTrace();
}
}
一个更好的解决方案是使用AnimationTimer。
以下是有关如何完成此操作的有用线程:JavaFX periodic background task