user3326720 user3326720 - 5 months ago 52
Java Question

JavaFX: How to find index of TreeItem in a TreeView?

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
?

Answer

The class TreeItem has a method named getParent, which returns the parent of the specified TreeItem. The 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(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent 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(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent 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"));
    }
});