JavaFX 8 图形线程管道

Posted

技术标签:

【中文标题】JavaFX 8 图形线程管道【英文标题】:JavaFX 8 graphic thread pipeline 【发布时间】:2018-06-03 04:01:22 【问题描述】:

我正在尝试添加在加载某些 javafx 图形时显示的加载对话框。问题是javafx图形的加载阻塞了加载对话框的刷新。

这是我的代码:

Stage dialogStage;
ProgressBar pb = new ProgressBar();
ProgressIndicator pin = new ProgressIndicator();
dialogStage = new Stage();
dialogStage.initStyle(StageStyle.UTILITY);
dialogStage.setResizable(false);
dialogStage.initModality(Modality.APPLICATION_MODAL);

// PROGRESS BAR
final Label label = new Label();
label.setText("alerto");

pb.setProgress(-1F);
pin.setProgress(-1F);

final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(pb, pin);

Scene scene = new Scene(hb);
dialogStage.setScene(scene);

final Task<Void> task = new Task<Void>() 
  @Override
  protected Void call() throws Exception 
    System.out.println(ANSI_CYAN + ANSI_RED_BACKGROUND + "START CALL" + ANSI_RESET);

    for (int i = 0; i < 1; i++) 
      System.out.println(ANSI_CYAN + "\tWAIT " + (i + 1) + "s;" + ANSI_RESET);
      try 
        Thread.sleep(500);
       catch (InterruptedException ex) 
        Logger.getLogger(FXMLDesktopController.class.getName()).log(Level.SEVERE, null, ex);
      
      System.out.println(ANSI_CYAN + "\tWAITED " + (i + 1) + "s;" + ANSI_RESET);
    

    Platform.runLater(() -> 
      System.out.println(ANSI_CYAN + ANSI_RED_BACKGROUND + "FIRE APP" + ANSI_RESET);

      startGraphic(anchorDesktop);

      System.out.println(ANSI_CYAN + ANSI_RED_BACKGROUND + "APP FIRED" + ANSI_RESET);
    );

    for (int i = 0; i < 0; i++) 
      System.out.println(ANSI_CYAN + "\tWAIT " + (i + 1) + "s;" + ANSI_RESET);
      try 
        Thread.sleep(1000);
       catch (InterruptedException ex) 
        Logger.getLogger(FXMLDesktopController.class.getName()).log(Level.SEVERE, null, ex);
      
      System.out.println(ANSI_CYAN + "\tWAITED " + (i + 1) + "s;" + ANSI_RESET);
    

    System.out.println(ANSI_CYAN + ANSI_RED_BACKGROUND + "END CALL" + ANSI_RESET);
    return null;
  

;

pb.progressProperty().bind(task.progressProperty());
pin.progressProperty().bind(task.progressProperty());
dialogStage.show();

task.setOnSucceeded(event -> 
  dialogStage.close();
  System.out.println(ANSI_CYAN + ANSI_RED_BACKGROUND + "CLOSE" + ANSI_RESET);
);

Platform.runLater(() -> 
  System.out.println(ANSI_CYAN + ANSI_RED_BACKGROUND + "START SHOW" + ANSI_RESET);
);

System.out.println(ANSI_CYAN + ANSI_RED_BACKGROUND + "NEW THEAD" + ANSI_RESET);

Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();

startGraphic(anchorDesktop) 被调用时,会阻止进度条的动画,直到所有图形加载完毕。 JavaFX 图形有多线程管道吗?

【问题讨论】:

您在 FX 应用程序线程上明确运行 startGraphic。该方法在做什么?如果它没有改变实际显示的任何内容,则可以在后台线程中运行。 【参考方案1】:

JavaFX 图形有多线程管道吗?

不,所有与 FX UI 相关的事情(有一些记录在案的例外情况)都必须在平台线程上完成。

目前您在平台线程上直接调用startGraphic(),因此无论该方法在做什么,它都必须在平台线程上发生任何其他事情之前完成执行(包括更新您的加载对话框。)

这可能有点痛苦,但在 UI 工具包中很常见。绕过它的正常方法(假设startGraphic() 进行了一堆 UI 初始化)将启动方法 off UI 线程,然后将各个 UI 操作包装在 Platform.runLater() 而不是一气呵成。在平台线程上拥有大量小型可运行程序将允许它在其间安排对 UI 的更新,包括对加载轮的更新。

【讨论】:

以上是关于JavaFX 8 图形线程管道的主要内容,如果未能解决你的问题,请参考以下文章

基于javafx如何用线程完成移动一个圆?

JavaFX 多线程之 ThreadPoolExecutor 线程池

JavaFX - SQL 查询的后台线程

JavaFX - SQL 查询的后台线程

JavaFX 多线程之 TaskServiceScheduledService

JavaFX 中的多线程会挂起 UI