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

Adding TableView with many columns in deep hierarchy is extremely slow

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • 9
    • 8u60
    • javafx
    • x86_64
    • windows_7

      FULL PRODUCT VERSION :
      java version "1.8.0_60"
      Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
      Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Windows 7 Enterprise SP1
      ver: Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      In our application we manage the different views by removing/adding them from/to scene graph dynamically. Some of the views contain the TableViews with non-trivial number of columns (50+). We noticed, that call node.getChildren().add(view) for such views takes 5+ seconds. Since this happens in javafx thread, this makes the whole application freeze for this duration.

      I managed to extract a self containing test case demonstrating the issue. Just keep clicking on the + button to remove/add the TableView with 288 columns. Adding the TableView takes 3 seconds on a modern Intel Core i7 processor.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Start the test case
      2) click + to hide the TableView
      3) click + to show the TableView, timing information appear in stdout
      repeat steps 2-3 if you like

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Nearly-instanteous appearance of TableView in the scenegraph, no freezing of the application
      ACTUAL -
      Application freeze for few seconds during addition

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.Arrays;

      import javafx.application.Application;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.collections.FXCollections;
      import javafx.geometry.Pos;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.control.cell.PropertyValueFactory;
      import javafx.scene.layout.AnchorPane;
      import javafx.scene.layout.HBox;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      public class FXTableViewExample extends Application {
          
          public static class Book {

              private SimpleStringProperty title;
              private SimpleStringProperty author;

              public Book() {
              }

              public Book(String s1, String s2) {
                  title = new SimpleStringProperty(s1);
                  author = new SimpleStringProperty(s2);
              }

              public String getTitle() {
                  return title.get();
              }

              public void setTitle(String s) {
                  title.set(s);
              }

              public String getAuthor() {
                  return author.get();
              }

              public void setAuthor(String s) {
                  author.set(s);
              }

          }

          public static void main(String [] args) {
              Application.launch(args);
          }

          @Override
          public void start(Stage primaryStage) {

              primaryStage.setTitle("Table View Example 1");

              // Books label
              Button showhide = new Button("+");
              HBox hb = new HBox();
              hb.setAlignment(Pos.CENTER);
              hb.getChildren().add(showhide);

              // Table view, data, columns and properties
              TableView<Book> table = new TableView<>();
              table.setItems(FXCollections.observableList(Arrays.asList(new Book("A", "B"))));

              String[] columns = {
                  "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
                  , "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author", "title", "author"
              };
              for (String prop : columns) {
                  TableColumn<Book, String> col = new TableColumn<>(prop);
                  col.setCellValueFactory(new PropertyValueFactory<>(prop));
                  table.getColumns().add(col);
              }
              table.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
              
              AnchorPane tmp = new AnchorPane(table);
              for (int i=0; i<50; i++) {
                  tmp = new AnchorPane(tmp);
                  AnchorPane.setTopAnchor(tmp, 0.0);
                  AnchorPane.setRightAnchor(tmp, 0.0);
                  AnchorPane.setBottomAnchor(tmp, 0.0);
                  AnchorPane.setLeftAnchor(tmp, 0.0);
              }
              final AnchorPane paneForTable = tmp;

              final VBox vbox = new VBox(20);
              vbox.getChildren().addAll(hb, paneForTable);
              
              showhide.setOnAction((event) -> {
                  if (!vbox.getChildren().remove(paneForTable)) {
                      long started = System.currentTimeMillis();
                      vbox.getChildren().add(paneForTable);
                      long duration = System.currentTimeMillis() - started;
                      System.out.println(String.format("Add took %d ms for %d columns", duration, table.getColumns().size()));
                  }
              });

              // Scene
              Scene scene = new Scene(vbox, 500, 475);
              primaryStage.setScene(scene);
              primaryStage.show();
          }
      }

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

            ckyang Chien Yang (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: