4 Replies Latest reply: Jan 28, 2013 10:09 AM by shakir.gusaroff RSS

    Locking the GUI, spinning dial (simillar to JXLayer)

    805439
      Hello,

      I am looking for a way to lock the GUI (and display a spinning dial) when a long running thread is running.
      How would one do this with JavaFX?

      Thanks in advance
        • 1. Re: Locking the GUI, spinning dial (simillar to JXLayer)
          jsmith
          scene.getRoot().setMouseTransparent(true);
          scene.setCursor(Cursor.WAIT);
          • 2. Re: Locking the GUI, spinning dial (simillar to JXLayer)
            shakir.gusaroff
            Hi.Here is an example:
             
            
            import javafx.application.Application;
            import javafx.beans.binding.When;
            import javafx.beans.property.ObjectProperty;
            import javafx.beans.property.SimpleObjectProperty;
            import javafx.concurrent.Task;
            import javafx.event.ActionEvent;
            import javafx.event.EventHandler;
            import javafx.scene.Scene;
            import javafx.scene.control.Button;
            import javafx.scene.layout.StackPane;
            import javafx.stage.Stage;
            import javafx.scene.Cursor;
            
            
            public class TaskProgrs extends Application {
                
                @Override
                public void start(Stage primaryStage) {
                    Button btn = new Button();
                    btn.setText("Submit");
                    btn.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent event) {
                            System.out.println("Hello World!");
                        }
                    });
                    
                    StackPane root = new StackPane();
                    root.getChildren().add(btn);
                    
                   final Scene scene = new Scene(root, 300, 250);
                    
                    primaryStage.setTitle("Hello World!");
                    primaryStage.setScene(scene);
                    primaryStage.show();
                    
                     Task<Integer> task = new Task<Integer>() {
                     @Override protected Integer call() throws Exception {
                         int iterations;
                         for (iterations = 0; iterations < 10000000; iterations++) {
                             if (isCancelled()) {
                                 updateMessage("Cancelled");
                                
                                 break;
                             }
                             updateMessage("Iteration " + iterations);
                             updateProgress(iterations, 10000000);
                         }
                         return iterations;
                     }
                 };
                    
                   
                    scene.getRoot().mouseTransparentProperty().bind(task.runningProperty()); 
                    scene.cursorProperty().bind(new When(task.runningProperty()).
                             then(new SimpleObjectProperty(Cursor.WAIT)).otherwise(new SimpleObjectProperty(Cursor.DEFAULT)));
                     Thread th = new Thread(task);
                     
                     th.start();
                    
                }
            
                /**
                 * The main() method is ignored in correctly deployed JavaFX application.
                 * main() serves only as fallback in case the application can not be
                 * launched through deployment artifacts, e.g., in IDEs with limited FX
                 * support. NetBeans ignores main().
                 *
                 * @param args the command line arguments
                 */
                public static void main(String[] args) {
                    launch(args);
                }
            }
            This works fine, except the cursor is not updated immediately because there is a bug:
            http://javafx-jira.kenai.com/browse/RT-21272
            Only when the mouse is moved for the first time after that, the change becomes visible.
            • 3. Re: Locking the GUI, spinning dial (simillar to JXLayer)
              984080
              Hey,

              Your example seems correct, but I wouldn't bind anything to your cursor..
              I guess you are binding for a 'waiting' cursor.

              You can use a ProgressIndicator instead!
              private final ProgressIndicator pi = new ProgressIndicator();
              pi.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);  // a waiting sign --> not value specific
              --> add the ProgressIndicator when starting the Task
              --> remove the ProgressIndicator when ending the Task.


              Add a listener on the Task like this
              myTask.stateProperty().addListener(chlTask);
              Start the task like this:
              new Thread(myTask).start();
              Your listener will look like this:
              ChangeListener chlTask = new ChangeListener<Worker.State>() {
              @Override
              public void changed(ObservableValue<? extends State> ov, State t, State newState) {
              if (newState == Worker.State.SUCCEEDED) {
              //task succeeded
              //remove your ProgressIndicator
              }
              else{...}
              }
              Good luck!

              Edited by: FXdude on 28-jan-2013 2:10
              • 4. Re: Locking the GUI, spinning dial (simillar to JXLayer)
                shakir.gusaroff
                Yes. Using a progress indicator instead of a cursor is a good idea.
                  
                   import javafx.application.Application;
                import javafx.beans.binding.When;
                import javafx.beans.property.ObjectProperty;
                import javafx.beans.property.SimpleObjectProperty;
                import javafx.beans.value.ChangeListener;
                import javafx.beans.value.ObservableValue;
                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.layout.StackPane;
                import javafx.stage.Stage;
                import javafx.scene.Cursor;
                import javafx.scene.control.ProgressIndicator;
                
                public class TaskProgs extends Application {
                
                    @Override
                    public void start(Stage primaryStage) {
                        Button btn = new Button();
                        btn.setText("Submit");
                        btn.setOnAction(new EventHandler<ActionEvent>() {
                            @Override
                            public void handle(ActionEvent event) {
                                System.out.println("click...");
                            }
                        });
                
                        final StackPane root = new StackPane();
                        root.getChildren().add(btn);
                
                        final Scene scene = new Scene(root, 300, 250);
                
                        primaryStage.setTitle("Hello World!");
                        primaryStage.setScene(scene);
                        primaryStage.show();
                
                        Task<Integer> task = new Task<Integer>() {
                            @Override
                            protected Integer call() throws Exception {
                                int iterations;
                                for (iterations = 0; iterations < 10000000; iterations++) {
                                    if (isCancelled()) {
                                        updateMessage("Cancelled");
                                        break;
                                    }
                                    updateMessage("Iteration " + iterations);
                                    updateProgress(iterations, 10000000);
                                }
                                return iterations;
                            }
                        };
                
                
                        final ProgressIndicator pi = new ProgressIndicator();
                        pi.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);  
                        scene.getRoot().mouseTransparentProperty().bind(task.runningProperty());
                        Thread th = new Thread(task);
                        th.start();
                        
                        task.stateProperty().addListener(new ChangeListener<State>() {
                            public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
                                if (newValue == State.SUCCEEDED) {
                                    root.getChildren().remove(pi);
                                } else if (newValue == State.RUNNING) {
                                    root.getChildren().add(pi);
                
                                }
                
                            }
                        });
                    }
                
                    public static void main(String[] args) {
                        launch(args);
                    }
                }