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

TreeView / TreeItem API: Overriding getChildren() results in wrong behavior



    • Bug
    • Resolution: Unresolved
    • P4
    • tbd
    • 7u45, 8
    • javafx


      The TreeItem API exposes the getChildren() method. The method is not marked final, therefore, I can override it.
      The behavior I was expecting is that, if I override this method, I can pass a different observable list then the default one.

      The below JFXTreeItem extends TreeItem by overriding getChildren(). However, when used in a treeView, I do not get children displayed on screen.

      public class JFXTreeItem<T> extends TreeItem<T> {

          private ObservableList<TreeItem<T>> children;

          public JFXTreeItem(T value, Node graphic) {
              super(value, graphic);
              children = FXCollections.observableArrayList();

          public ObservableList<TreeItem<T>> getChildren() {
              return children;

      A closer look at the TreeItem code reveals two problems:
      1- getChildren() in TreeItem is setting a changeListener (which is private and not exposed to subclasses). Therefore any overriding of getChildren() will loose this changeListener. I am referring to the code below from TreeItem :

      public ObservableList<TreeItem<T>> getChildren()
          if (this.children == null) {
            this.children = FXCollections.observableArrayList();

          if (this.children.isEmpty()) return this.children;


          return this.children;

      2- The code of TreeItem does not consistently call getChildren(), and at times will call <this.children>. Since the only exposed API is getChildren(), the value in this.children becomes irrelevant if the developer overrided getChildren(). As an example, the sort method :

       void sort()
          sort(this.children, this.lastComparator, this.lastSortMode);

      The only way where changing the children list works is by a hack through reflection. Something like the code below:

         public JFXTreeItem(T value, Node graphic) {
              super(value, graphic);

              ObservableList<TreeItem<T>> children = FXCollections.observableArrayList();

              try {
                  Field childrenField = TreeItem.class.getDeclaredField("children");
                  childrenField.set(this, children);

                  Field declaredField = TreeItem.class.getDeclaredField("childrenListener");
                  children.addListener((ListChangeListener<? super TreeItem<T>>) declaredField.get(this));

              } catch (Exception e) {

      This code works, and items are displayed on the screen correctly.

      However, I don't think as an end developer I should resort to this tweak.
      Either the getChildren() remains available for overriding , and the internals of TreeItem get fixed.
      Or getChildren() should be declared final, and therefore the developer knows that overriding it won't work.




            Unassigned Unassigned
            rashajfx rasha (Inactive)
            1 Vote for this issue
            5 Start watching this issue