5 Replies Latest reply: Feb 19, 2013 8:48 PM by SlashWang RSS

    javaFX have ProgressMonitorDialog like jface? ProgressIndicator don't help.

    SlashWang
      javaFX have ProgressMonitorDialog like jface? ProgressIndicator don't help.


      I need a loading page like ProgressMonitorDialog in jface.
      Then when i do some time-consuming operation, a loading page will be loaded until the operation is over.
      The problem is that when i use a Service class, i must put the time-consuming operation outside the Platform.runLater(new Runnable().
      and i must put the javaFX controls set operation in the Platform.runLater(new Runnable(), it's very difficult to seperate them sometimes.

      ProgressIndicator doesn't help in this case.

      Thank you.


           button.setOnMouseClicked(new EventHandler<MouseEvent>() {
                     public void handle(MouseEvent me) {
                          stage.show();
                          
                          final Task<Integer> task = new Task<Integer>()
      {

      @Override
      protected Integer call()
      throws Exception
      {
      // TODO Auto-generated method stub
      System.out.println("ssss");
      try
      {
      Thread.sleep(5000);
      }
      catch (InterruptedException e)
      {
      // TODO Auto-generated catch block
      e.printStackTrace();
      }
                                    
      Platform.runLater(new Runnable()
      {

      @Override
      public void run()
      {
                                         // when do something time-consuming here, then stage.Show(); above can't be loaded immediately when button clicked //,why? The thread will always wait the time-consuming operation.
      button2.setText("dddddddd");
      stage.close();
      }
      });
      // TODO Auto-generated method stub
      return null;
      }
      };
                          Service<Integer> service = new Service<Integer>()
      {

      @Override
      protected Task<Integer> createTask()
      {
      // TODO Auto-generated method stub
      return task;
      }
      };
      service.start();
                          }});
        • 1. Re: javaFX have ProgressMonitorDialog like jface? ProgressIndicator don't help.
          James_D
          >
          I need a loading page like ProgressMonitorDialog in jface.
          Then when i do some time-consuming operation, a loading page will be loaded until the operation is over.
          The problem is that when i use a Service class, i must put the time-consuming operation outside the Platform.runLater(new Runnable().
          and i must put the javaFX controls set operation in the Platform.runLater(new Runnable(), it's very difficult to seperate them sometimes.
          Use the various update(...) methods in the Task class, such as updateProgress(...). These will cause changes to the Task (and Service) properties, and these changes will be made on the FX Application thread for you.

          You can also listen for changes to the state property of the service, or use the various utility methods such as setOnSucceeded(...) to execute code when the service finishes running. Again, these methods are executed on the FX Application thread, so you don't need to manage the Platform.runLater(...) yourself.
          ProgressIndicator doesn't help in this case.
          Why not?


          There are lots of examples out there. Here's another one :)
          import javafx.application.Application;
          import javafx.beans.binding.Bindings;
          import javafx.beans.value.ChangeListener;
          import javafx.beans.value.ObservableValue;
          import javafx.concurrent.Service;
          import javafx.concurrent.Task;
          import javafx.concurrent.Worker.State;
          import javafx.event.ActionEvent;
          import javafx.event.EventHandler;
          import javafx.scene.Scene;
          import javafx.scene.control.Button;
          import javafx.scene.control.Label;
          import javafx.scene.control.ProgressIndicator;
          import javafx.scene.layout.BorderPane;
          import javafx.stage.Modality;
          import javafx.stage.Stage;
          
          public class ProgressDialogDemo extends Application {
          
            @Override
            public void start(Stage primaryStage) {
          
              final BorderPane root = new BorderPane();
              Button button = new Button("Click me to start...");
              root.setTop(button);
          
              final Service<Void> service = new Service<Void>() {
                @Override
                protected Task<Void> createTask() {
                  return new Task<Void>() {
                    @Override
                    protected Void call() throws Exception {
                      final int numThingsToDo = 50;
                      for (int i = 0; i < numThingsToDo && !isCancelled(); i++) {
                        Thread.sleep(100);
                        updateProgress(i + 1, numThingsToDo);
                      }
                      return null;
                    }
                  };
                }
              };
          
              // Disable button while service is running:
              button.disableProperty().bind(service.runningProperty());
          
              final Stage progressDialog = createProgressDialog(service, primaryStage);
          
              button.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                  progressDialog.show();
                  service.reset();
                  service.start();
                }
              });
          
              final Label status = new Label();
              status.textProperty().bind(Bindings.format("%s", service.stateProperty()));
              root.setBottom(status);
          
              Scene scene = new Scene(root, 400, 400);
              primaryStage.setScene(scene);
              primaryStage.show();
            }
          
            private Stage createProgressDialog(final Service<Void> service, Stage owner) {
              final Stage stage = new Stage();
              stage.initModality(Modality.WINDOW_MODAL);
              stage.initOwner(owner);
              final BorderPane root = new BorderPane();
              final ProgressIndicator indicator = new ProgressIndicator();
              // have the indicator display the progress of the service:
              indicator.progressProperty().bind(service.progressProperty());
              // hide the stage when the service stops running:
              service.stateProperty().addListener(new ChangeListener<State>() {
                @Override
                public void changed(ObservableValue<? extends State> observable,
                    State oldValue, State newValue) {
                  if (newValue == State.CANCELLED || newValue == State.FAILED
                      || newValue == State.SUCCEEDED) {
                    stage.hide();
                  }
                }
              });
              // A cancel button:
              Button cancel = new Button("Cancel");
              cancel.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                  service.cancel();
                }
              });
              root.setCenter(indicator);
              root.setBottom(cancel);
              Scene scene = new Scene(root, 200, 200);
              stage.setScene(scene);
              return stage;
            }
          
            public static void main(String[] args) {
              launch(args);
            }
          }
          • 2. Re: javaFX have ProgressMonitorDialog like jface? ProgressIndicator don't help.
            SlashWang
            Use the various update(...) methods in the Task class, such as updateProgress(...). These will cause changes to the Task (and Service) properties, and these changes will be made on the FX Application thread for you.
            --->
            Thank you very much ,James.

            The problem is that my code can't use the updateProgress(...), 'cause there is no progress(percentage) here in my code.

            final int numThingsToDo = 50;
            for (int i = 0; i < numThingsToDo && !isCancelled(); i++) {
            Thread.sleep(100);
            updateProgress(i + 1, numThingsToDo);
            }
            is useless for me .

            Pls tell me that :
            1 whether when the time-consuming code logic in Service is over, then the service.stateProperty would be State.SUCCEEDED??
            2 I can't write javaFX code(set properties on javaFX controllers) in the Service<Void> service. So I MUST separate these code from my logic code , how can I always separate them?

            Best Wishes.
            • 3. Re: javaFX have ProgressMonitorDialog like jface? ProgressIndicator don't help.
              James_D
              >
              The problem is that my code can't use the updateProgress(...), 'cause there is no progress(percentage) here in my code.

              final int numThingsToDo = 50;
              for (int i = 0; i < numThingsToDo && !isCancelled(); i++) {
              Thread.sleep(100);
              updateProgress(i + 1, numThingsToDo);
              }
              is useless for me .
              There's also an updateMessage(String msg) you can call, which will update the message property (on the FX Application Thread). If you are just changing a String, you can bind to the message property and use this method.
              Something like
              button.textProperty().bind(service.messageProperty());
              Otherwise you have to use Platform.runLater(...):
                  final Service<Void> service = new Service<Void>() {
                    @Override
                    protected Task<Void> createTask() {
                      return new Task<Void>() {
                        @Override
                        protected Void call() throws Exception {
                          final int numThingsToDo = 50;
                          for (int i = 0; i < numThingsToDo && !isCancelled(); i++) {
                            Thread.sleep(100);
                            Platform.runLater(new Runnable() {
                              @Override
                              public void run() {
                                // update UI here
                              }
                            });
                          }
                          return null;
                        }
                      };
                    }
                  };
              Note that when Java 8 is out you can reduce this to
              Platform.runLater( () -> { // update ; ui ; here ; } );
              The examples in http://docs.oracle.com/javafx/2/api/index.html pretty much cover all the options.
              Pls tell me that :
              1 whether when the time-consuming code logic in Service is over, then the service.stateProperty would be State.SUCCEEDED??
              Assuming it completed normally, yes. If the call() method in the Task exits due to an exception, it would be State.FAILED. If it exits with the canceled flag set, it will be State.CANCELLED.
              2 I can't write javaFX code(set properties on javaFX controllers) in the Service<Void> service. So I MUST separate these code from my logic code , how can I always separate them?
              Use Platform.runLater(...) as above.