java.lang.IllegalStateException: Not on FX application thread解决办法

今天爱分享给大家java.lang.IllegalStateException: Not on FX application thread解决办法,希望能够帮助到大家。

问题描述
运行javaFX程序,系统会自动创建一个FX application thread线程,用于更新界面的组件信息,例如ListView的items、Label的text。当我们想运用多线程实现业务,而自己创建的线程又直接导致了界面组件信息的更新时,控制台就会抛出java.lang.IllegalStateException异常。

完整异常栈如下
Exception in thread “pool-2-thread-1” java.lang.IllegalStateException: Not on FX application thread; currentThread = pool-2-thread-1
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent2. o n P r o p o s e d C h a n g e ( P a r e n t . j a v a : 367 ) a t c o m . s u n . j a v a f x . c o l l e c t i o n s . V e t o a b l e L i s t D e c o r a t o r . s e t A l l ( V e t o a b l e L i s t D e c o r a t o r . j a v a : 113 ) a t c o m . s u n . j a v a f x . c o l l e c t i o n s . V e t o a b l e L i s t D e c o r a t o r . s e t A l l ( V e t o a b l e L i s t D e c o r a t o r . j a v a : 108 ) a t c o m . s u n . j a v a f x . s c e n e . c o n t r o l . s k i n . L a b e l e d S k i n B a s e . u p d a t e C h i l d r e n ( L a b e l e d S k i n B a s e . j a v a : 575 ) a t c o m . s u n . j a v a f x . s c e n e . c o n t r o l . s k i n . L a b e l e d S k i n B a s e . h a n d l e C o n t r o l P r o p e r t y C h a n g e d ( L a b e l e d S k i n B a s e . j a v a : 204 ) a t c o m . s u n . j a v a f x . s c e n e . c o n t r o l . s k i n . L a b e l S k i n . h a n d l e C o n t r o l P r o p e r t y C h a n g e d ( L a b e l S k i n . j a v a : 49 ) a t c o m . s u n . j a v a f x . s c e n e . c o n t r o l . s k i n . B e h a v i o r S k i n B a s e . l a m b d a 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.lambda2.onProposedChange(Parent.java:367)atcom.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)atcom.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)atcom.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:575)atcom.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:204)atcom.sun.javafx.scene.control.skin.LabelSkin.handleControlPropertyChanged(LabelSkin.java:49)atcom.sun.javafx.scene.control.skin.BehaviorSkinBase.lambdaregisterChangeListener$61(BehaviorSkinBase.java:197)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler1. c h a n g e d ( M u l t i p l e P r o p e r t y C h a n g e L i s t e n e r H a n d l e r . j a v a : 55 ) a t j a v a f x . b e a n s . v a l u e . W e a k C h a n g e L i s t e n e r . c h a n g e d ( W e a k C h a n g e L i s t e n e r . j a v a : 89 ) a t c o m . s u n . j a v a f x . b i n d i n g . E x p r e s s i o n H e l p e r 1.changed(MultiplePropertyChangeListenerHandler.java:55) at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89) at com.sun.javafx.binding.ExpressionHelper1.changed(MultiplePropertyChangeListenerHandler.java:55)atjavafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)atcom.sun.javafx.binding.ExpressionHelperSingleChange.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 controller.RootLayoutController.updateLabel(RootLayoutController.java:255)
at controller.RootLayoutController.getReady(RootLayoutController.java:238)
at controller.RootLayoutController.lambda$login2 ( R o o t L a y o u t C o n t r o l l e r . j a v a : 221 ) a t j a v a . u t i l . c o n c u r r e n t . T h r e a d P o o l E x e c u t o r . r u n W o r k e r ( T h r e a d P o o l E x e c u t o r . j a v a : 1149 ) a t j a v a . u t i l . c o n c u r r e n t . T h r e a d P o o l E x e c u t o r 2(RootLayoutController.java:221) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor2(RootLayoutController.java:221)atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)atjava.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

解决方案
之所以抛出异常,是因为javaFX程序不允许用户在FX application thread线程外更新界面的组件信息,换句话说,所有的更新界面组件的信息的代码,都应该在在FX application thread线程中执行。解决办法还是有的,用Platform类的runLater方法可以解决该问题。

runLater方法的定义如下
public static void runLater(Runnable runnable) {
  PlatformImpl.runLater(runnable);
}

通过阅读javaAPI文档,可以知晓,该方法可以将参数runnable将要执行的代码,交给FX application thread线程执行,这样问题就解决了。具体解决模板如下。

假设在一个自己创建的线程中,调用了update()方法,update()方法用于更新主界面的组件信息,这会导致如题的异常
此时,可以如下调用update()方法
Platform.runLater(()->{
  update();
   //任何更新界面组件信息的代码
});

人已赞赏
Java

如何解决 Spring Security Oauth2中refresh token 获取到的新的token 无法进行刷新Token

2020-10-16 18:05:39

Java

vue打包后运行报Uncaught SyntaxError: Unexpected token '<'?解决办法

2020-10-16 18:48:20

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
'); })();