0
votes

I have a node with several children and want to keep the collapse/expand arrow that is the default icon of the node, but I have another graphic that I would like to put right next to the arrow. Does the JavaFX treeview allow a way to do this?

1

1 Answers

0
votes

Either just pass the graphic to the TreeItem:

TreeItem<String> root = new TreeItem<>("Root", new Rectangle(16, 16, Color.CORAL));

etc,

or use a cell factory:

TreeView<String> tree = new TreeView<>();
tree.setCellFactory(tv -> new TreeCell<String>() {
    private final Node graphic = new Rectangle(16, 16, Color.CORAL);
    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        setGraphic(empty ? null : graphic);
        setText(empty ? null : item);
    }
});

Note that for large trees, the second technique has the potential to be far more efficient, as it only creates graphics (two nodes in this case) for each cell, whereas the first technique creates graphics for every item in the tree (whether or not it is displayed). Arguably (I would strongly argue), the second technique has better separation of concerns (in the first solution the graphic is part of data, which is just plain wrong).

SSCCE for first technique:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class TreeGraphicTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        TreeItem<String> root = new TreeItem<>("Root", new Rectangle(16, 16, Color.CORAL));
        for (int i = 1 ; i <= 3 ; i++) {
            root.getChildren().add(new TreeItem<>("Child "+i, new Rectangle(16, 16, Color.CORNFLOWERBLUE)));
        }
        TreeView<String> tree = new TreeView<>(root);
        primaryStage.setScene(new Scene(tree));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

SSCCE for second technique:

import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class TreeGraphicTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        TreeItem<String> root = new TreeItem<>("Root");
        for (int i = 1 ; i <= 3 ; i++) {
            root.getChildren().add(new TreeItem<>("Child "+i));
        }
        TreeView<String> tree = new TreeView<>(root);
        tree.setCellFactory(tv -> new TreeCell<String>() {
            private final Node rootGraphic = new Rectangle(16, 16, Color.CORAL) ;
            private final Node childGraphic = new Rectangle(16, 16, Color.CORNFLOWERBLUE) ;
            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                setGraphic(empty ? null : getTreeItem() == root ? rootGraphic : childGraphic);
                setText(empty ? null : item);
            }
        });
        primaryStage.setScene(new Scene(tree));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Screenshot (for either):

enter image description here