JavaFX: How to find index of TreeItem in a TreeView

javajavafxtreeview

I have a TreeView and a Button in my program. Whenever this Button is clicked, it adds a new element right after the element selected last in the TreeView.
enter image description here

For example, if I were to select the "Test Action" element and click the "Add" button, it should add another TreeItem right after "Test Action", but before "Test Condition".

I've written code so that I can keep track of the element selected last:

@FXML
TreeView<String> view;
TreeItem<String> current = root;
view.selectionModelProperty().addListener(new ChangeListener<MultipleSelectionModel<TreeItem<String>>>() {

            @Override
            public void changed(ObservableValue<? extends MultipleSelectionModel<TreeItem<String>>> observable,
                    MultipleSelectionModel<TreeItem<String>> oldValue,
                    MultipleSelectionModel<TreeItem<String>> newValue) {
                    current = newValue.getSelectedItem();
            }
});

However, through the use of the TreeItem, "current", there is no method I can use to find its index in the TreeView.

This is so that I can do:

root.getChildren().add(index, new TreeItem<String>(new OpenBank().getAction(), Icons.ACTION.getIcon()));

So is there a way to find a child's index in a TreeView?

Best Answer

The class TreeItem has a method getParent, which returns the parent of the specified TreeItem. This parent, which is also a TreeItem has a method getChildren to get the child TreeItems; the order of TreeItems in the returned ObservableList is the actual order that you can see on the screen, therefore you can insert a new element in a specific index with add after you retrieved the index of the element in the list with indexOf().

You can simply handle the current selection in the event listener of your Button:

Button b = new Button("Add");
b.setOnAction(event -> {
    // Get the selected item
    TreeItem<String> selectedItem = treeView.getSelectionModel().getSelectedItem();

    // If there is no selection or the root is selected do nothing
    if (selectedItem == null || selectedItem == rootNode)
        return;

    // Otherwise get the index of the Node from the children of its parent
    // and append the new item right after it
    int index = selectedItem.getParent().getChildren().indexOf(selectedItem);
    selectedItem.getParent().getChildren().add(index+1, new TreeItem<>("New Item"));
});

If you already tracking the current selection:

The modification is just to use current (that's how you named your variable) rather than getting the selection in the handler:

Button b = new Button("Add");
b.setOnAction(event -> {
    // If there is no selection or the root is selected do nothing
    if (current == null || current == rootNode)
        return;

    // Otherwise get the index of the Node from the children of its parent
    // and append the new item right after it
    int index = current.getParent().getChildren().indexOf(current);
    current.getParent().getChildren().add(index+1, new TreeItem<>("New Item"));
});