Nested Paths to JavaFX TreeView

时间:2017-03-22 18:39:41

标签: java javafx tree treeview

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 个答案:

答案 0 :(得分:1)

您可以遍历您的字符串列表,用分隔符(.)拆分每个字符串,然后在树中搜索,根据需要添加项目。类似的东西:

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

请注意,这里的字符串没什么特别之处,你可以用任何类型做到这一点。这是一个使用该方法的通用版本的SSCCE:

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

答案 1 :(得分:1)

将项目“path”存储在地图中,以便您可以查找它们,创建不存在的节点并使用现有节点。最简单的方法是使用递归方法:

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