You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Enum在JavaFX中动态生成TreeView

基于层级Enum动态构建JavaFX TreeView的解决方案

你遇到的问题其实很典型——从预定义层级的枚举里构建TreeView,和数据库数据源的区别在于枚举是内存里的固定数据,我们只需要梳理清楚它的父节点关联关系就行。下面我给你一套完整的实现思路和代码:

第一步:完善TreeItems枚举的基础方法

首先得把TreeItems里的属性getter补上,这样我们才能方便地获取每个节点的上下文、父节点和显示名称:

public enum TreeItems {
    AM_ROOT(MenuContext.APP, null, ""),
    NODE_1(MenuContext.APP, AM_ROOT, "Menu node 1"),
    NODE_2(MenuContext.APP, AM_ROOT, "Menu node 2"),
    NODE_2_1(MenuContext.APP, NODE_2, "Menu node 2.1"),
    NODE_2_2(MenuContext.APP, NODE_2, "Menu node 2.2"),
    NODE_2_3(MenuContext.APP, NODE_2, "Menu node 2.3"),
    NODE_2_4(MenuContext.APP, NODE_2, "Menu node 2.4"),
    NODE_3(MenuContext.APP, AM_ROOT, "Menu node 3"),
    NODE_4(MenuContext.APP, AM_ROOT, "Menu node 4"),
    DM_ROOT(MenuContext.DIALOG, null, ""),
    DM_NODE_1(MenuContext.DIALOG, DM_ROOT, "Dialog menu node 1"),
    DM_NODE_2(MenuContext.DIALOG, DM_ROOT, "Dialog menu node 2"),
    DM_NODE_2_1(MenuContext.DIALOG, DM_NODE_2, "Dialog menu node 2.1"),
    DM_NODE_2_2(MenuContext.DIALOG, DM_NODE_2, "Dialog menu node 2.2"),
    DM_NODE_2_3(MenuContext.DIALOG, DM_NODE_2, "Dialog menu node 2.3"),
    DM_NODE_2_4(MenuContext.DIALOG, DM_NODE_2, "Dialog menu node 2.4"),
    DM_NODE_3(MenuContext.DIALOG, DM_ROOT, "Dialog menu node 3");

    private final MenuContext menuContext;
    private final TreeItems parent;
    private final String displayName;

    TreeItems(MenuContext menuContext, TreeItems parent, String displayName) {
        this.menuContext = menuContext;
        this.parent = parent;
        this.displayName = displayName;
    }

    // 新增getter方法
    public MenuContext getMenuContext() {
        return menuContext;
    }

    public TreeItems getParent() {
        return parent;
    }

    public String getDisplayName() {
        return displayName;
    }
}

第二步:编写TreeView构建工具类

接下来写一个工具方法,核心逻辑是:

  • 先筛选出指定MenuContext下的所有枚举项
  • 找到该上下文下的根节点(parent为null的项)
  • 递归为每个节点添加对应的子节点
  • 最终组装成TreeView

代码示例:

import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class TreeViewBuilder {

    public static TreeView<String> buildTreeView(MenuContext context) {
        // 筛选当前上下文下的所有节点
        List<TreeItems> allNodes = Arrays.stream(TreeItems.values())
                .filter(item -> item.getMenuContext() == context)
                .collect(Collectors.toList());

        // 找到根节点(parent为null的节点)
        TreeItems rootEnum = allNodes.stream()
                .filter(item -> item.getParent() == null)
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("No root node found for context: " + context));

        // 构建根TreeItem,为空时用上下文名称显示
        TreeItem<String> rootItem = new TreeItem<>(
                rootEnum.getDisplayName().isEmpty() ? context.name() : rootEnum.getDisplayName()
        );
        rootItem.setExpanded(true); // 默认展开根节点

        // 递归添加子节点
        addChildNodes(rootEnum, rootItem, allNodes);

        // 创建TreeView并返回
        TreeView<String> treeView = new TreeView<>(rootItem);
        treeView.setShowRoot(true); // 不想显示根节点可设为false
        return treeView;
    }

    private static void addChildNodes(TreeItems parentEnum, TreeItem<String> parentTreeItem, List<TreeItems> allNodes) {
        // 找到当前父节点下的所有子节点
        List<TreeItems> childNodes = allNodes.stream()
                .filter(item -> parentEnum.equals(item.getParent()))
                .collect(Collectors.toList());

        // 为每个子节点创建TreeItem并递归处理其子节点
        for (TreeItems childEnum : childNodes) {
            TreeItem<String> childTreeItem = new TreeItem<>(childEnum.getDisplayName());
            parentTreeItem.getChildren().add(childTreeItem);
            addChildNodes(childEnum, childTreeItem, allNodes);
        }
    }
}

第三步:测试使用

在你的JavaFX应用里,直接调用工具方法就能生成对应上下文的TreeView:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class TreeViewDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
        // 构建APP上下文的TreeView
        TreeView<String> appTree = TreeViewBuilder.buildTreeView(MenuContext.APP);
        // 或者构建DIALOG上下文的TreeView
        // TreeView<String> dialogTree = TreeViewBuilder.buildTreeView(MenuContext.DIALOG);

        StackPane root = new StackPane(appTree);
        Scene scene = new Scene(root, 300, 400);
        primaryStage.setTitle("Dynamic TreeView from Enum");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

关键逻辑说明

  • 用流式API筛选目标上下文的节点,避免处理无关枚举项
  • 递归方法addChildNodes逐层遍历节点关系,自动构建TreeItem层级
  • 根节点显示文本做了兼容处理,为空时用上下文名称替代,你可以根据需求调整

这样就能完美适配你的枚举结构,动态生成对应的TreeView了!

内容的提问来源于stack exchange,提问作者PatrickT80

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:36:10