Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8170459

Indeterminate ProgressIndicator degrades performance if stage changed

XMLWordPrintable

    • x86_64
    • windows_7

      FULL PRODUCT VERSION :
      java version "1.8.0_111"
      Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      If there is an indeterminate progress indicator showing, any type of stage/scene interaction degrades the application performance.

      For example, while a progress indicator is showing, these types of interactions can produce the issue:
      - Creating a new stage/scene
      - User resizing the stage
      - Programatically resizing the stage (as is done in the included source example)

      The problem is not immediately noticeable, a number of interactions typically have to be performed for it to become apparent to the user.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the included source:
      - Click the Menu, opens as normal
      - Click the Run Resize Task button, a series of stage resize operations are performed
      - Click the Menu again, now there is a noticeable lag (~2 seconds) for the menu to open
      - The problem becomes progressively worse the more times the resize task is run

      As noted in the description, the user manually resizing the window a lot can produce the same behavior.


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import javafx.application.Application;
      import javafx.concurrent.Task;
      import javafx.scene.Group;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.Menu;
      import javafx.scene.control.MenuBar;
      import javafx.scene.control.MenuItem;
      import javafx.scene.control.ProgressIndicator;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      /**
       * Example demonstrating issue with stage resizing when indeterminate progress indicator is showing.
       */
      public class TestApplication extends Application {

          private void init(Stage primaryStage) {
              // Create new scene for stage
              Group root = new Group();
              primaryStage.setScene(new Scene(root));
              primaryStage.setWidth(200);
              primaryStage.setHeight(200);
              
              // Create menu bar with a single menu+item
              MenuBar menuBar = new MenuBar();
              Menu menu = new Menu("Menu");
              MenuItem menuItem = new MenuItem("Menu Item");
              menu.getItems().add(menuItem);
              menuBar.getMenus().addAll(menu);
              
              // Create button that runs the resize task
              Button button = new Button("Run Resize Task");
              button.setOnAction((event) -> {
                  button.setDisable(true);
                  runResizeTask(primaryStage, () -> {
                      button.setDisable(false);
                  });
              });
              
              // Create indeterminate progress indicator
              ProgressIndicator progressIndicator = new ProgressIndicator();
              progressIndicator.setMaxSize(75, 75);
              
              // Add all elements to vbox
              VBox vBox = new VBox();
              vBox.spacingProperty().set(10);
              vBox.getChildren().addAll(menuBar, button, progressIndicator);
              root.getChildren().add(vBox);
          }

          private void runResizeTask(Stage stage, Runnable callback) {
              // Expand and contract the stage size in a task
              Task<Void> task = new Task<Void>() {
                  @Override
                  protected Void call() throws Exception {
                      for (int i = 200; i < 600; i++) {
                          stage.setWidth(i);
                          stage.setHeight(i);
                          Thread.sleep(5);
                      }
                      for (int i = 600; i > 200; i--) {
                          stage.setWidth(i);
                          stage.setHeight(i);
                          Thread.sleep(5);
                      }
                      
                      callback.run();
                      return null;
                  }
              };
              
              // Start the task in a new thread
              Thread thread = new Thread(task);
              thread.setDaemon(true);
              thread.start();
          }
          
          @Override
          public void start(Stage primaryStage) throws Exception {
              init(primaryStage);
              primaryStage.show();
          }
          
          public static void main(String[] args) {
              launch(args);
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Using a determinate ProgressIndicator and binding it to a service does not have this same issue.

      However this does have limitations as the UI elements are different.

            flar Jim Graham
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: