import java.util.ArrayList; import java.util.Random; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.stage.Stage; public class TestTreeView extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { TreeView treeView = new TreeView<>(); Group g = new Group(); g.getChildren().addAll(treeView); primaryStage.setScene(new Scene(g, 500, 400)); primaryStage.show(); TreeItem root = new DynamicTreeItem(0); root.setValue("root"); treeView.setRoot(root); root.setExpanded(true); treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener>() { @Override public void changed(ObservableValue> observable, TreeItem oldVal, TreeItem newVal) { System.out.println("Selected: "+newVal + " (oldval:"+oldVal+")"); } }); } } class DynamicTreeItem extends TreeItem { private boolean isFirstTimeChildren = true; private boolean isLeaf = false; private int depth; private static final int MAX_DEPTH=5; private Random rand = new Random(); public DynamicTreeItem(int depth) { this.depth = depth; if(depth >= MAX_DEPTH) isLeaf = true; } @Override public boolean isLeaf() { return isLeaf; } @Override public ObservableList> getChildren() { //dynamically load children first time in if (isFirstTimeChildren) { isFirstTimeChildren = false; super.getChildren().setAll(buildChildren(this)); } return super.getChildren(); } private ObservableList buildChildren(DynamicTreeItem itm) { //build a random number of nodes int items = rand.nextInt(20)+1; ArrayList list = new ArrayList<>(); int childdepth = depth+1; for(int i=0; i children = FXCollections.observableList(list); return children; } }