首页 > 解决方案 > 嵌套 JavaFX 的 TreeView 的有效数量

问题描述

My Class Category 本身可能具有parentCategory或是根Category,然后parentCategory设置为null. 每个都Category可能有子类别

我的Category班级代码:

public class Category extends AbstractEntity<Integer> {

    @ManyToOne(cascade = { CascadeType.ALL, CascadeType.REMOVE })
    @JoinColumn(name = "parentCategory_id")
    private Category parentCategory;

    @OneToMany(mappedBy = "parentCategory", fetch = FetchType.EAGER)
    private Set<Category> subcategories;
    private String name;

    @OneToMany(cascade = { CascadeType.ALL, CascadeType.REMOVE }, fetch = FetchType.EAGER)
    private List<Item> items;

    public Category(String name) {
    this.subcategories = new HashSet<>();
    this.name = name;
    this.items = new ArrayList<>();
    }
...
}

假设我的数据库中有很多带有子类别的类别。我想用 javafx 显示类别的层次结构,TreeView但以通用方式而不需要手动填充TreeItems。不幸的是,我可以很容易地只显示根类别的直接子类别

我测试的代码:

    public void initialize(URL paramURL, ResourceBundle paramResourceBundle) {

    List<Category> categoriesAll = categoryDao.findAll();

    categories.getSelectionModel().selectedItemProperty()
        .addListener((ObservableValue<? extends Category> observable, Category oldValue, Category newValue) -> {

        });

    categories.getItems().addAll(FXCollections.observableArrayList(categoriesAll));

    TreeItem<String> rootNode = new TreeItem<>("Categories");
    rootNode.setExpanded(true);

    List<Category> superCategories = categoriesAll.stream().filter(category -> !category.hasParentCategory())
        .collect(Collectors.toList());

    Map<Category, TreeItem<String>> nodesMap = new HashMap<>();
    for (Category cat : superCategories) {
        TreeItem<String> leaf = new TreeItem<String>(cat.getName());
        addTreeItems(0, cat, nodesMap);
        rootNode.getChildren().add(leaf);
    }

    rootNode.getChildren().get(0).getChildren().add(nodesMap.entrySet().stream()
        .filter(entry -> entry.getKey().getName().equals("automotive")).findFirst().get().getValue());

    categoriesTree.setRoot(rootNode);

    }

    public void addTreeItems(int index, Category category, Map<Category, TreeItem<String>> nodesMap) {
    // System.out.println(index + " " + category.getName());
    nodesMap.put(category, new TreeItem<String>(category.getName()));
    List<TreeItem<String>> childrenCategories = category.getSubcategories().stream()
        .map(c -> new TreeItem<String>(c.getName())).collect(Collectors.toList());
    nodesMap.get(category).getChildren().addAll(childrenCategories);
    category.getSubcategories().forEach(cat -> addTreeItems(index + 1, cat, nodesMap));
    }

输出是(在 treeView 组件中):

automotive
|_tires and rims
|_auto parts
|_cars
|_car workshop equipment

但应该是:

automotive
|_tires and rims
| |_winter tires
| |_summer tires
|_auto parts
|_cars
| |_audi
| | |_a4
| |_nissan
|  |_gtr
|_car workshop equipment

标签: javajavafxtreeview

解决方案


因此,我为嵌套数据层次结构的问题制定了解决方案。此问题的解决方案是查找没有父级的根类别。

List<Category> superCategories = categoriesAll.stream().filter(category -> !category.hasParentCategory())
        .collect(Collectors.toList());

然后每个superCategory都被视为根本身:

TreeItem<String> rootNode = new TreeItem<>("Categories");
rootNode.setExpanded(true);
superCategories.forEach(superCategory -> Utils.buildRoot(superCategory, rootNode));

buildRoot方法:

public static void buildRoot(Category category, TreeItem<String> root) {
    if (category.hasParentCategory()) {
        TreeItem<String> found = find(root, category.getParentCategory().getName());
        if (found != null) {
            found.getChildren().add(new TreeItem<String>(category.getName()));
        }
    } else {
        root.getChildren().add(new TreeItem<String>(category.getName()));
    }
    category.getSubcategories().forEach(subcategory -> buildRoot(subcategory, root));
}

find方法:

private static TreeItem<String> find(TreeItem<String> root, String value) {
    if (root != null) {
        if (root.getValue().equals(value)) {
            return root;
        }
        ObservableList<TreeItem<String>> children = root.getChildren();
        if (children != null) {
            for (TreeItem<String> child : children) {
                if (child.getValue().equals(value)) {
                    return child;
                }
                return find(child, value);
            }
        }
    }
    return null;
}

推荐阅读