Class TreeItem<T>

java.lang.Object
javafx.scene.control.TreeItem<T>
Type Parameters:
T - The type of the value property within TreeItem.
All Implemented Interfaces:
EventTarget
Direct Known Subclasses:
CheckBoxTreeItem

public class TreeItem<T> extends Object implements EventTarget
The model for a single node supplying a hierarchy of values to a control such as TreeView. The model may be implemented such that values may be loaded in memory as they are needed.

The model allows registration of listeners which will be notified as the number of items changes, their position or if the values themselves change. Note however that a TreeItem is not a Node, and therefore no visual events will be fired on the TreeItem. To get these events, it is necessary to add relevant observers to the TreeCell instances (via a custom cell factory - see the Cell class documentation for more details).

In the simplest case, TreeItem instances may be created in memory as such:


 TreeItem<String> root = new TreeItem<String>("Root Node");
 root.setExpanded(true);
 root.getChildren().addAll(
     new TreeItem<String>("Item 1"),
     new TreeItem<String>("Item 2"),
     new TreeItem<String>("Item 3")
 );
 TreeView<String> treeView = new TreeView<String>(root);
 
This approach works well for simple tree structures, or when the data is not excessive (so that it can easily fit in memory). In situations where the size of the tree structure is unknown (and therefore potentially huge), there is the option of creating TreeItem instances on-demand in a memory-efficient way. To demonstrate this, the code below creates a file system browser:

  private TreeView buildFileSystemBrowser() {
      TreeItem<File> root = createNode(new File("/"));
      return new TreeView<File>(root);
  }

  // This method creates a TreeItem to represent the given File. It does this
  // by overriding the TreeItem.getChildren() and TreeItem.isLeaf() methods
  // anonymously, but this could be better abstracted by creating a
  // 'FileTreeItem' subclass of TreeItem. However, this is left as an exercise
  // for the reader.
  private TreeItem<File> createNode(final File f) {
      return new TreeItem<File>(f) {
          // We cache whether the File is a leaf or not. A File is a leaf if
          // it is not a directory and does not have any files contained within
          // it. We cache this as isLeaf() is called often, and doing the
          // actual check on File is expensive.
          private boolean isLeaf;

          // We do the children and leaf testing only once, and then set these
          // booleans to false so that we do not check again during this
          // run. A more complete implementation may need to handle more
          // dynamic file system situations (such as where a folder has files
          // added after the TreeView is shown). Again, this is left as an
          // exercise for the reader.
          private boolean isFirstTimeChildren = true;
          private boolean isFirstTimeLeaf = true;

          @Override public ObservableList<TreeItem<File>> getChildren() {
              if (isFirstTimeChildren) {
                  isFirstTimeChildren = false;

                  // First getChildren() call, so we actually go off and
                  // determine the children of the File contained in this TreeItem.
                  super.getChildren().setAll(buildChildren(this));
              }
              return super.getChildren();
          }

          @Override public boolean isLeaf() {
              if (isFirstTimeLeaf) {
                  isFirstTimeLeaf = false;
                  File f = (File) getValue();
                  isLeaf = f.isFile();
              }

              return isLeaf;
          }

          private ObservableList<TreeItem<File>> buildChildren(TreeItem<File> TreeItem) {
              File f = TreeItem.getValue();
              if (f != null && f.isDirectory()) {
                  File[] files = f.listFiles();
                  if (files != null) {
                      ObservableList<TreeItem<File>> children = FXCollections.observableArrayList();

                      for (File childFile : files) {
                          children.add(createNode(childFile));
                      }

                      return children;
                  }
              }

              return FXCollections.emptyObservableList();
          }
      };
  }
TreeItem Events

TreeItem supports the same event bubbling concept as elsewhere in the scenegraph. This means that it is not necessary to listen for events on all TreeItems (and this is certainly not encouraged!). A better, and far more low cost solution is to instead attach event listeners to the TreeView root item. As long as there is a path between where the event occurs and the root TreeItem, the event will be bubbled to the root item.

It is important to note however that a TreeItem is not a Node, which means that only the event types defined in TreeItem will be delivered. To listen to general events (for example mouse interactions), it is necessary to add the necessary listeners to the cells contained within the TreeView (by providing a cell factory).

The TreeItem class defines a number of events, with a defined hierarchy. These are shown below (follow the links to learn more about each event type):

The indentation shown above signifies the relationship between event types. For example, all TreeItem event types have treeNotificationEvent() as their parent event type, and the branch expand / collapse event types are both treeNotificationEvent(). For performance reasons, it is encouraged to listen to only the events you need to listen to. This means that it is encouraged that it is better to listen to, for example, TreeItem.valueChangedEvent(), rather than TreeItem.treeNotificationEvent().

Since:
JavaFX 2.0
See Also: