Hello,大家好。我是 78KgMiao。
相信很多使用JavaFx的小伙伴都遇到过这个问题。Not on FX application thread;
造成这个问题的原因呢,就是没有在JavaFx的UI线程中绘制。
不管是JavaSwing也好,JavaFx也罢。都会把UI绘制放到一个独立的线程中。避免其他线程去刷新UI。如果说外部线程可以绘制UI的话,那不就乱套了吗。
代码案例
package com.beishu.clip.text;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class NotonFX extends Application {
@Override
public void start(Stage stage) throws Exception {
Pane root = new Pane();
Scene scene = new Scene(root, 500, 300);
stage.setTitle("Not on FX application thread");
stage.setScene(scene);
stage.show();
new Thread(() -> {
// TODO 耗时操作...
VBox pane = new VBox();
pane.getChildren().add(new Label("78KgMiao"));// 1
pane.getChildren().add(new TextField("78KgMiao"));// 2
// root.getChildren().add(pane);// 3 此处会报错
// 4 更新UI
Platform.runLater(() -> {
root.getChildren().add(pane);
});
}).start();
}
public static void main(String[] args) {
launch(args);
}
}
异常堆栈信息
Exception in thread "Thread-3" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:291)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:446)
at javafx.scene.Parent$3.onProposedChange(Parent.java:474)
at com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
at com.beishu.clip.text.NotonFX.lambda$0(NotonFX.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
案例分析
案例很简单,创建了一个VBox
,然后分别在1
和2
处添加一个Label
和一个TextField
。如果打开注释3
,那么会报如上错误信息。解决办法就是用注释4
处的方法。
那么是不是所有的类似add, addAll
等方法都需要使用Platform.runLater(() -> {//TODO});
处理呢?参考注释1,2
,你会发现其实不是这样的。
教大家一个判断标准:
如果这一行代码运行之后,页面的UI会发生肉眼可见的变化,那么就需要使用Platform.runLater处理。否则的话不用。