如何从JavaFX中的值集合动态生成树视图

如何从JavaFX中的值集合动态生成树视图,java,javafx,treeview,Java,Javafx,Treeview,出于学习的目的,我想从一个枚举动态构建一个树视图,我在其中定义了树项及其关系 菜单上下文枚举 public enum MenuContext { APP, // Tree menu of application DIALOG; // Tree menu on dialog } public enum TreeItems { AM_ROOT(MenuContext.APP, null, ""), NODE_1(MenuContext.APP, AM_ROOT, "Menu node 1"

出于学习的目的,我想从一个枚举动态构建一个树视图,我在其中定义了树项及其关系

菜单上下文枚举

public enum MenuContext {
 APP, // Tree menu of application
 DIALOG; // Tree menu on dialog
}
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");

 // Necessary code to get values of single enum item
}
TreeItems枚举

public enum MenuContext {
 APP, // Tree menu of application
 DIALOG; // Tree menu on dialog
}
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");

 // Necessary code to get values of single enum item
}
通过这种结构,我尝试在上的答案之后动态创建树,我看到问题和答案被引用到数据库以存储树信息


因此,我的问题是,如何将构建算法适应于数据的枚举源,因为当我尝试使用提出的代码和答案动态构建树时,我可以一个接一个地获得树项列表,而不是按父项分组。

经过多次尝试和失败,我找到了一种方法,可以使用这种方法从对象集合中动态构建树状视图,这些对象按其父对象分组

private TreeView<String> buildTree(MenuContext mC) {
 List<TreeItems> roots = buildParents(mC);
 EnumMap<TreeItems, TreeItem<String>> values = buildTreeValues(mC);
 TreeView<String> tree = new TreeView<>();
 TreeItem<String> root = null;
 int rootsSize = roots.size();
 // Build node w or w/o children in reverse order
 for (int i = rootsSize - 1; i > 0; --i) {
  EnumMap<TreeItems, TreeItem<String>> nodeChildren = getNodeChildren(roots.get(i),values);
  for (Entry<TreeItems, TreeItem<String>> entry : nodeChildren.entrySet()) {
   values.get(roots.get(i)).getChildren().add(entry.getValue());
   values.remove(entry.getKey());
  }
 }
 // Populate tree model
 for (Entry<TreeItems, TreeItem<String>> entry : values.entrySet()) {
  if (entry.getKey().getParent() == null) {
   root = entry.getValue();
  } else {
   if (root == null) {
    root = entry.getValue();
   } else {
    root.getChildren().add(entry.getValue());
   }
  }
 }
 tree.setRoot(root);
 tree.setShowRoot(false);
 return tree;
}

private EnumMap<TreeItems, TreeItem<String>> buildTreeValues(MenuContext mC) {
 EnumMap<TreeItems, TreeItem<String>> treeValues = new EnumMap<>(TreeItems.class);
 for (TreeItems tI : TreeItems.values()) {
  if (tI.getMenuContext().equals(mC)) {
   treeValues.put(tI, new TreeItem<>(tI.getLabel()));
  }
 }
 return treeValues;
}

private List<TreeItems> buildParents(MenuContext mC) {
 List<TreeItems> parents = new ArrayList<>();
 for (TreeItems tI : TreeItems.values()) {
  if (tI.getMenuContext().equals(mC) && !parents.contains(tI.getParent())) {
   parents.add(tI.getParent());
  }
 }
 return parents;
}

private EnumMap<TreeItems, TreeItem<String>> getNodeChildren(TreeItems root,
 EnumMap<TreeItems, TreeItem<String>> values) {
 EnumMap<TreeItems, TreeItem<String>> cNodes = new EnumMap<>(TreeItems.class);
 for (Entry<TreeItems, TreeItem<String>> entry : values.entrySet()) {
  TreeItems parentKey = entry.getKey().getParent();
  if (parentKey != null && root.equals(parentKey)) {
   cNodes.put(entry.getKey(), entry.getValue());
  }
 }
 return cNodes;
}
私有树视图构建树(MenuContext mC){
列表根=构建父级(mC);
EnumMap值=buildTreeValues(mC);
TreeView tree=新的TreeView();
TreeItem root=null;
int rootsSize=roots.size();
//按相反顺序生成有子节点或无子节点的节点
对于(int i=rootsSize-1;i>0;--i){
EnumMap nodeChildren=getNodeChildren(root.get(i),值);
for(条目:nodeChildren.entrySet()){
value.get(root.get(i)).getChildren().add(entry.getValue());
移除(entry.getKey());
}
}
//填充树模型
for(条目:values.entrySet()){
if(entry.getKey().getParent()==null){
root=entry.getValue();
}否则{
if(root==null){
root=entry.getValue();
}否则{
root.getChildren().add(entry.getValue());
}
}
}
树根;
tree.setShowRoot(false);
回归树;
}
私有EnumMap buildTreeValues(MenuContext mC){
EnumMap treeValues=新的EnumMap(TreeItems.class);
for(TreeItems tI:TreeItems.values()){
如果(tI.getMenuContext()等于(mC)){
put(tI,新的TreeItem(tI.getLabel());
}
}
返回树值;
}
私有列表构建父对象(MenuContext mC){
List parents=new ArrayList();
for(TreeItems tI:TreeItems.values()){
如果(tI.getMenuContext().equals(mC)&&!parents.contains(tI.getParent())){
parents.add(tI.getParent());
}
}
返回父母;
}
私有EnumMap getNodeChildren(TreeItems根目录,
枚举映射值){
EnumMap cNodes=新的EnumMap(TreeItems.class);
for(条目:values.entrySet()){
TreeItems parentKey=entry.getKey().getParent();
if(parentKey!=null&&root.equals(parentKey)){
cNodes.put(entry.getKey(),entry.getValue());
}
}
返回cNodes;
}
我已经测试了这个实现,手动使用了一个具有三级嵌套的枚举,并生成了一个树来显示按父级正确分组的值