如何基于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
相关产品推荐
相关产品推荐

