0

Any ideas on how to represent nested paths within as TreeItems?

This is my input as several Strings (besides: I don't know the strings before so the whole thing should be as generic as possible):

input1 input2.sub1 input2.sub2 input2.sub2.subsub1 input2.sub3 input3 input3.sub1 input3.sub1.subsub1 input3.sub1.subsub1.subsubsub1 input3.sub2 

Since I'm on the way at the moment, I cannot post any source code unfortunately. But before asking, I tried several approaches such as transferring the paths directly to the TreeView (seems complicated) or having some sort of tree representation in java first (mostly everything with recursive methods).

The attached screenshots shows what I try to achieve in a generic way. TreeView

Thanks a lot in advance — best wishes from Germany :)

2 Answers 2

1

You can iterate through your list of strings, split each one by the delimiter (.), and then search through the tree, adding items as needed. Something like:

List<String> paths = ... ; TreeItem<String> root = new TreeItem<>("root"); for (String path : paths) { TreeItem<String> current = root ; for (String component : path.split("\\.")) { current = getOrCreateChild(current, component); } } // ... private TreeItem<String> getOrCreateChild(TreeItem<String> parent, String value) { for (TreeItem<String> child : parent.getChildren()) { if (value.equals(child.getValue())) { return child ; } } TreeItem<String> newChild = new TreeItem<>(value); parent.getChildren().add(newChild); return newChild ; } 

Note there's nothing particularly special about strings here, you could do this with any type. Here's a SSCCE which uses a generic version of the method:

import java.util.Arrays; import java.util.List; import java.util.function.Function; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.stage.Stage; public class TreeFromPaths extends Application { private final List<String> paths = Arrays.asList( "input1", "input2.sub1", "input2.sub2", "input2.sub2.subsub1", "input2.sub3", "input3", "input3.sub1", "input3.sub1.subsub1", "input3.sub1.subsub1.subsubsub1", "input3.sub2" ); private <S,T> TreeView<T> createTree( List<S> paths, Function<S, ? extends Iterable<T>> pathSplitter, T rootValue) { TreeItem<T> root = new TreeItem<>(rootValue); populateTree(paths, pathSplitter, root); TreeView<T> tree = new TreeView<>(root); tree.setShowRoot(false); return tree; } private <S,T> void populateTree( List<S> paths, Function<S, ? extends Iterable<T>> pathSplitter, TreeItem<T> root) { for (S path : paths) { TreeItem<T> current = root ; for (T component : pathSplitter.apply(path)) { current = getOrCreateChild(current, component); } } } private <T> TreeItem<T> getOrCreateChild(TreeItem<T> parent, T value) { for (TreeItem<T> child : parent.getChildren()) { if (value.equals(child.getValue())) { return child ; } } TreeItem<T> newChild = new TreeItem<>(value); parent.getChildren().add(newChild); return newChild ; } @Override public void start(Stage primaryStage) { Function<String, List<String>> pathSplitter = path -> Arrays.asList(path.split("\\.")); TreeView<String> treeView = createTree(paths, pathSplitter, "root"); primaryStage.setScene(new Scene(treeView, 400, 400)); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 
Sign up to request clarification or add additional context in comments.

1 Comment

Genius! Thanks a bunch! That worked perfectly fine and is a very compact solution according to my problem.
1

Store the items "path" in a map so that you can look them up, create nodes that do not exist and use existing nodes. The easiest way to do this would be a recursive method:

private static TreeItem<String> getItem(Map<String, TreeItem<String>> items, TreeItem<String> root, String itemPath) { TreeItem<String> result = items.get(itemPath); if (result == null) { // new item needs to be created int index = itemPath.lastIndexOf('.'); result = new TreeItem<>(itemPath.substring(index + 1)); items.put(itemPath, result); if (index == -1) { // no more subpaths => connect to root root.getChildren().add(result); } else { // find/create parent TreeItem<String> parent = getItem(items, root, itemPath.substring(0, index)); parent.getChildren().add(result); } } return result; } @Override public void start(Stage primaryStage) throws Exception { List<String> paths = Arrays.asList( "input1", "input2.sub1", "input2.sub2", "input2.sub2.subsub1", "input2.sub3", "input3", "input3.sub1", "input3.sub1.subsub1", "input3.sub1.subsub1.subsubsub1", "input3.sub2"); TreeItem<String> root = new TreeItem<>(); Map<String, TreeItem<String>> items = new HashMap<>(); for (String path : paths) { getItem(items, root, path); } TreeView<String> treeView = new TreeView<>(root); treeView.setShowRoot(false); Scene scene = new Scene(treeView); primaryStage.setScene(scene); primaryStage.show(); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.