Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 622
Catscratch Avatar asked Dec 04 '22 03:12

Catscratch


2 Answers

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.

like image 160
gfkri Avatar answered Dec 28 '22 07:12

gfkri


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

like image 22
KayDK Avatar answered Dec 28 '22 08:12

KayDK