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

TreeTableRow skins are not consistent

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Incomplete
    • Icon: P3 P3
    • None
    • 8u40, 8u45
    • javafx

      I'm trying to customize TreeTableView by extending the TreeTableView and overriding the Row skin.
      At first when I run the application all skins are created for each row according to its index
      ( Index 0 RowSkin0, index 1 RowSkin1 ,... ) however after expanding the and collapsing some nodes in the tree table and repeating it for 50 times a new trailing row is created and the skins start to rotate over the index, which is messing the behavior of the treetable ( Index 0 NewRowSkin, index 1 RowSkin0, Index 2 RowSkin1,....). it starts flashing while expanding/collapsing.

      Note that at this stage every expand/collapse will change the order of the row skin.
      e.g after 1 expand/collapse operation the map become ( index 0 LastRowSkin, index 1 newRowSkin, index 2 RowSkin0, index 3 RowSkin 1, ... ) and so on.

      - this behavior is noticed in JDK 1.8 u 40 and above.
      - this behavior is not found in JDK 1.8 u 25.
      - also this behavior is ONLY noticed when applying the css , to be specific its ONLY noticed when adding
      padding to the cell :
      .tree-table-view .tree-table-cell{
      -fx-border-width:0 0 0 0;
      -fx-padding : 16 0 16 0 ;
      }


      Below is the code and CSS used:


      import javafx.application.Application;
      import javafx.beans.property.ReadOnlyStringWrapper;
      import javafx.geometry.Insets;
      import javafx.scene.Scene;
      import javafx.scene.control.Skin;
      import javafx.scene.control.TreeItem;
      import javafx.scene.control.TreeTableColumn;
      import javafx.scene.control.TreeTableRow;
      import javafx.scene.control.TreeTableView;
      import javafx.scene.layout.StackPane;
      import javafx.stage.Stage;
      import javafx.util.Callback;

      import com.sun.javafx.scene.control.skin.TreeTableRowSkin;

      public class Demo extends Application {

      final TreeItem<User> root = new TreeItem<>(new User("Sales Department", "23"));

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

      @Override
      public void start(Stage primaryStage) throws Exception {
      root.getChildren().add(new TreeItem<>(new User("Sales Department1", "23")));
      TreeItem<User> root1 = new TreeItem<>(new User("Sales Department2", "24"));
      root.getChildren().add(root1);
      root1.getChildren().add(new TreeItem<>(new User("Sales Department3", "25")));


      root.getChildren().add(new TreeItem<>(new User("Sales Department4", "22")));
      TreeItem<User> root2 = new TreeItem<>(new User("Sales Department5", "20"));
      root.getChildren().add(root2);
      root2.getChildren().add(new TreeItem<>(new User("Sales Department6", "21")));


      TreeTableColumn<User, String> empColumn =
      new TreeTableColumn<>("User");
      empColumn.setPrefWidth(150);
      empColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<User, String> param) ->
      new ReadOnlyStringWrapper(param.getValue().getValue().userName));

      TreeTableColumn<User, String> ageColumn =
      new TreeTableColumn<>("Age");
      ageColumn.setPrefWidth(150);
      ageColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<User, String> param) ->
      new ReadOnlyStringWrapper(param.getValue().getValue().age));



      CustomTreeTableView<User> treeView = new CustomTreeTableView<User>(root);
      treeView.setShowRoot(false);
      treeView.getColumns().setAll(empColumn, ageColumn);

      StackPane main = new StackPane();
      main.setPadding(new Insets(10));
      main.getChildren().add(treeView);
      Scene scene = new Scene(main, 600, 400);
      scene.getStylesheets().add(Demo.class.getResource("css/styles.css").toExternalForm());
      primaryStage.setScene(scene);
      primaryStage.show();

      }

      class User {
      String userName;
      String age;
      public User(String userName, String age) {
      this.userName = userName;
      this.age = age;
      }

      }


      private class CustomTreeTableView<S> extends TreeTableView<S> {
      public CustomTreeTableView(TreeItem<S> root) {
      super(root);
      this.setRowFactory(new Callback<TreeTableView<S>, TreeTableRow<S>>() {
      @Override
      public TreeTableRow<S> call(TreeTableView<S> param) {
      return new CustomTreeTableRow<S>();
      }
      });
      }
      }

      private class CustomTreeTableRow<T> extends TreeTableRow<T> {
      @Override protected Skin<?> createDefaultSkin() {
      return new CustomTreeTableRowSkin<T>(this);
      }
      }

      private class CustomTreeTableRowSkin<T> extends TreeTableRowSkin<T> {
      public CustomTreeTableRowSkin(TreeTableRow<T> control) {
      super(control);
      System.out.println("Row Skin " + getSkinnable().getIndex() + " is created");
      }

      @Override
      protected void layoutChildren(final double x, final double y, final double w, final double h) {
      super.layoutChildren(x, y, w, h);
      System.out.println("ROW : " + getSkinnable().getIndex()+ " : " + CustomTreeTableRowSkin.this);
      }
      }

      }



      /*
       * TREE TABLE CSS
       */

      .tree-table-view{
      -fx-tree-table-color: rgba(255, 0, 0, 0.2);
      -fx-tree-table-rippler-color : rgba(255, 0, 0, 0.4);
      }
       .tree-table-view:focused .tree-table-row-cell:selected {
      -fx-background-color: -fx-tree-table-color ;
      -fx-table-cell-border-color: -fx-tree-table-color;
      -fx-text-fill: BLACK;
      }

       .tree-table-view:focused .tree-table-row-cell:selected .tree-table-cell{
      -fx-text-fill: BLACK;
      }

      .tree-table-view .c3d-rippler {
      -fx-rippler-fill: -fx-tree-table-rippler-color;
      }

      .tree-table-view .column-header ,
      .tree-table-view .column-header-background,
      .tree-table-view .column-header-background .filler{
      -fx-background-color:TRANSPARENT;
      }

      .tree-table-view .column-header{
      -fx-border-width : 0 1 0 1;
      -fx-border-color: #F3F3F3;
      }

      .tree-table-view .column-header .label {
      -fx-text-fill : #949494;
      -fx-padding : 16 0 16 0 ;
      }

      .tree-table-view .column-header .arrow {
      -fx-background-color : #949494;
      }

      .tree-table-view .column-header:last-visible {
      -fx-border-width: 0 2 0 1;
      }

      .tree-table-view .column-header-background{
      -fx-border-width : 0 0.0 1 0;
      -fx-border-color:#F3F3F3;
      }

      .tree-table-view .tree-table-cell{
      -fx-border-width:0 0 0 0;
      -fx-padding : 16 0 16 0 ;
      }

      .tree-table-view .column-overlay{
      -fx-background-color: -fx-tree-table-color;
      }

      .tree-table-view .column-resize-line, .tree-table-view .column-drag-header{
      -fx-background-color: -fx-tree-table-rippler-color;
      }

      .tree-table-view:focused {
        -fx-background-color: -fx-tree-table-color,-fx-box-border,-fx-control-inner-background;
        -fx-background-insets: -1.4, 0, 1;
        -fx-background-radius: 1.4, 0, 0;
        /*....*/
        -fx-padding: 1; /* 0.083333em; */
      }

      .tree-table-row-cell > .tree-disclosure-node > .arrow {
          -fx-background-color: -fx-text-fill;
          -fx-padding: 0.333333em 0.229em 0.333333em 0.229em; /* 4 */
          -fx-shape: "M 0 -3.5 L 4 0 L 0 3.5 z";
      }


            jgiles Jonathan Giles
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: