Is it possible to generate a JavaFX TreeItem's children dynamically based on a function?
Asked Answered
C

1

6

Intro:

I am currently working on my first TreeView in JavaFX.

The example given in the documentation is the following:

 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);

In this example, we build the TreeItem tree structure manually, i.e., calling getChildren() on every node that has children and adding these.

Question:

Is it possible to tell a TreeItem to "dynamically" build its children? It would be perfect if I could define the parent-child-relationship as a function.

I would be looking for something like the following:

// Function that generates the child tree items for a given tree item
Function<TreeItem<MyData>, List<TreeItem<MyData>>> childFunction = parent -> {
  List<TreeItem<MyData>> children = new ArrayList<>(
    parent.                                                    // TreeItem<MyData>
      getValue().                                              // MyData
      getChildrenInMyData().                                   // List<MyData>
      stream().
      map(myDataChild -> new TreeItem<MyData>(myDataChild)))); // List<TreeItem<MyData>>
  // The children should use the same child function
  children.stream().forEach(treeItem -> treeItem.setChildFunction(childFunction));
  return children;
};

TreeItem<MyData> root = new TreeItem<MyData>(myRootData);
root.setExpanded(true);
// THE IMPORTANT LINE:
// Instead of setting the children via .getChildren().addAll(...) I would like to set a "child function"
root.setChildFunction(childFunction);  
TreeView<MyData> treeView = new TreeView<String>(root);
Comma answered 10/8, 2017 at 7:44 Comment(6)
not with core TreeItem - but you could implement a custom TreeItem that accepts a functionDoby
Yeah, I thought that I would have to end up with this. It should not be hard, but I don't understand why they haven't included something like this...Comma
no idea, just guessing: it started before java8?Doby
Ah, you are right...Comma
@kleopatra: As you said, I implemented a custom TreeItem. I posted it as answer.Comma
already seen and upvoted :)Doby
C
3

Since there is no built-in functionality for this (as pointed out by @kleopatra in the comments), I came up with the following TreeItem implementation:

public class AutomatedTreeItem<C, D> extends TreeItem<D> {
    public AutomatedTreeItem(C container, Function<C, D> dataFunction, Function<C, Collection<? extends C>> childFunction) {
        super(dataFunction.apply(container));
        getChildren().addAll(childFunction.apply(container)
                .stream()
                .map(childContainer -> new AutomatedTreeItem<C, D>(childContainer, dataFunction, childFunction))
                .collect(Collectors.toList()));
    }
}

Example usage:

Function<MyData, MyData> dataFunction = c -> c;
Function<MyData, Collection<? extends MyData>> childFunction = c -> c.getChildren();

treeTableView.setRoot(new AutomatedTreeItem<MyData, MyData>(myRootData, dataFunction, childFunction));

Probably this will help someone in the future.

Comma answered 10/8, 2017 at 10:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.