Hello,大家好,我是 78KgMiao。
场景分析
相信很多使用JavaFx的小伙伴都遇到过这个问题。Not on FX application thread;
造成这个问题的原因呢,就是没有在JavaFx的UI线程中绘制。
不管是JavaSwing也好,JavaFx也罢。都会把UI绘制放到一个独立的线程中。避免其他线程去刷新UI。如果说外部线程可以绘制UI的话,那不就乱套了吗。
代码案例
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(() -> {
// 1 TODO 耗时操作...
VBox pane = new VBox();// 2
pane.getChildren().add(new Label("78KgMiao"));// 3
pane.getChildren().add(new TextField("78KgMiao"));// 4
// root.getChildren().add(pane);// 5 此处会报错
// 6 更新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)
代码分析
- 注释
1
:执行耗时操作。- 注释
2,3,4
:执行耗时操作过程中,我们需要去更新UI。案例中我们创建了一个VBox
,然后添加了两个组件Label
和TextFiled
。注意:此处并没有报错。(因为只是添加,并没有引起UI的变化)- 注释
5
:如果打开注释5,注意:此处会报如上错误信息。(因为这行代码引起了UI的变化)- 注释
6
:使用Platform.runLater(() -> {//TODO});
解决注释5中出现的问题。
经验总结:如果这一行代码运行之后,页面的UI会发生肉眼可见的变化,那么就需要使用Platform.runLater处理。否则的话不用。