JavaFX显示加载对话框以进行更长时间的操作

时间:2015-04-30 09:08:03

标签: asynchronous concurrency javafx runnable

我在Controller类中进行了一些操作可能需要一些时间。所以我想在此操作运行时显示加载对话框。

我试过了:

Platform.runLater(new Runnable() {
  @Override
  public void run() {
     loadingDialog.show();
  }
});

Boolean opSuccess = myService.operate();

Platform.runLater(new Runnable() {
   @Override
   public void run() {
     loadingDialog.hide();
   }
});

if (opSuccess) {
   // continue
}

现在,问题是,loadingDialog永远不会显示。 UI只会阻塞一段时间,而不是继续“//继续”。

看来,阻塞操作(操作)阻止了runLater调用?

我还尝试了CoundDownLatch,等待loadDialog.show()完成,然后再运行myService.operate()。但是latch.await()方法永远不会完成。

所以我的问题是,在myService.operate()完成并返回true或false之前,我如何显示loadingDialog?我是否必须将operate()调用放入另一个线程并运行异步或是否有更简单的方法?

感谢您的帮助。

2 个答案:

答案 0 :(得分:13)

您确定您的整个代码不能在JavaFX Thread中运行吗? 你的控制器类的方法通常是这样做的,我假设它是由于你的描述。

但是,最好使用Task类。 Here您可以找到适合您应用的教程和简短代码段:

// here runs the JavaFX thread
// Boolean as generic parameter since you want to return it
Task<Boolean> task = new Task<Boolean>() {
    @Override public Boolean call() {
        // do your operation in here
        return myService.operate();
    }
};

task.setOnRunning((e) -> loadingDialog.show());
task.setOnSucceeded((e) -> {
    loadingDialog.hide();
    Boolean returnValue = task.get();
    // process return value again in JavaFX thread
});
task.setOnFailed((e) -> {
  // eventual error handling by catching exceptions from task.get()  
});
new Thread(task).start();

我假设Java 8和使用Lambda表达式的可能性。当然没有它们是可能的。

答案 1 :(得分:1)

最好在JavaFx中使用并发机制/工作器接口 - 任务和服务,而不是使用Platform.runLater()。任务和服务允许您在单独的线程中管理长时间运行的任务。它们还提供回调以指示任务的进度。

您可以在http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

进一步探索

另请参阅任务和服务的Ensemble JavaFX示例 - http://www.oracle.com/technetwork/java/javase/overview/javafx-samples-2158687.html