Catscratch
Catscratch

Reputation: 698

JavaFX show loading dialog for longer operations

I got some operations in my Controller class which could take some time. So I want to show a loading dialog while this operation is running.

I tried this:

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
}

Now, the Problem is, the loadingDialog is never show. The UI only blocks for some time and than continues on "//continue".

So it seems, the runLater call is blocked by the blocking operation (operate)?

I also tried CoundDownLatch, to wait for loadingDialog.show() to complete, before running myService.operate(). But the latch.await() method never completes.

So my question is, how my I show the loadingDialog until myService.operate() finished and returned true or false? Do I have to put the operate() call into another thread and run it async or is there an easier way?

Thanks for help.

Upvotes: 5

Views: 8728

Answers (2)

gfkri
gfkri

Reputation: 2179

Are you sure your entire code does not run in the JavaFX Thread? Methods of your controller class usually do and I assume it due to your description.

However, better use the Task class. Here you'll find a tutorial and a short snippet for your application:

// 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();

I assumed Java 8 and the possibility to use Lambda expressions. Of course it is possible without them.

Upvotes: 16

KayDK
KayDK

Reputation: 134

You are better off making use of concurrency mechanisms/Worker interfaces in JavaFx - Tasks and services instead of using Platform.runLater(). The tasks and services allow you to manage the long running tasks in a separate thread. They also provide callbacks to indicate the progress of the tasks.

You could explore further at http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

Also have a look at the Ensemble JavaFX samples for Tasks and Services - http://www.oracle.com/technetwork/java/javase/overview/javafx-samples-2158687.html

Upvotes: 1

Related Questions