2017-12-25 10 views
0

조직도 트리가 필요하며 모든 수준에서 노드를 축소하고 확장 할 수 있기를 원합니다. 저는 JGraphX를 처음 사용 합니다만, 접기를 구현하는 방법과 같이 꼭 읽어야 할 것은 정점을 그룹화하는 것입니다. 문제는 그룹을 만들 때 모든 자식 정점을 부모 정점 안에 배치하는 것입니다.JGraphX에서 접을 수있는 노드로 계층 적 트리를 만드는 방법

package com.mxgraph.examples.swing; 

import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JFrame; 
import javax.swing.SwingConstants; 

import com.mxgraph.layout.mxCompactTreeLayout; 
import com.mxgraph.layout.hierarchical.mxHierarchicalLayout; 
import com.mxgraph.model.mxGeometry; 
import com.mxgraph.swing.mxGraphComponent; 
import com.mxgraph.util.mxConstants; 
import com.mxgraph.util.mxPoint; 
import com.mxgraph.util.mxRectangle; 
import com.mxgraph.view.mxGraph; 
import com.mxgraph.layout.hierarchical.mxHierarchicalLayout; 
public class HelloWorld extends JFrame 
{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -2707712944901661771L; 

    public HelloWorld() 
    { 
     super("Hello, puppies!"); 

     mxGraph graph = new mxGraph(); 
     Object parent = graph.getDefaultParent(); 

     graph.getModel().beginUpdate(); 
     try 
     { 
      //Notice that the parent is the default parent... 
      //The hierarchical structure looks great but I cannot collapse/expand the tree. 
      Object vDogsRoot = graph.insertVertex(parent, null, "DOG", 0, 0, 80, 30); 
      Object v2 = graph.insertVertex(parent, null, "Shar Pei", 0, 0, 80, 30); 
      Object v3 = graph.insertVertex(parent, null, "Pug", 0, 0, 80, 30); 
      Object v4 = graph.insertVertex(parent, null, "Cocker Spaniel", 0, 0, 80, 30); 
      Object v5 = graph.insertVertex(parent, null, "Pit Bull", 0, 0, 80, 30); 
      Object v6 = graph.insertVertex(parent, null, "Chihuahua", 0, 0, 80, 30); 

      graph.insertEdge(parent, null, "", vDogsRoot, v2); 
      graph.insertEdge(parent, null, "", vDogsRoot, v3); 
      graph.insertEdge(parent, null, "", vDogsRoot, v4); 
      graph.insertEdge(parent, null, "", vDogsRoot, v5); 
      graph.insertEdge(parent, null, "", vDogsRoot, v6); 

      mxHierarchicalLayout layout = new mxHierarchicalLayout(graph); 
      layout.setUseBoundingBox(false); 

      layout.execute(parent); 
     } 
     finally 
     { 
      graph.getModel().endUpdate(); 
     } 

     mxGraphComponent graphComponent = new mxGraphComponent(graph); 
     getContentPane().add(graphComponent); 
    } 

    public static void main(String[] args) 
    { 
     HelloWorld frame = new HelloWorld(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(400, 320); 
     frame.setVisible(true); 
    } 

} 

가 생산 :

First code produces this image

위대한 시작하지만 축소 버튼을 여기에

은 좋은 레이아웃을 제공하지만, 폴딩을 지원하지 않는 몇 가지 예제 코드입니다. 다음 코드는 내가 가지고있는 문제를 보여줍니다. 접기를 지원하기 위해 기본 부모에서 트리의 루트 인 vDogVertex까지 정점의 부모를 변경하여 그룹을 만들려고합니다. 이것은 접을 수있게되지만 모든 자식 정점은 vDogVertex 내부에 있으며 트리 레이아웃이 망가져 있습니다.

package com.mxgraph.examples.swing; 

import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JFrame; 
import javax.swing.SwingConstants; 

import com.mxgraph.layout.mxCompactTreeLayout; 
import com.mxgraph.layout.hierarchical.mxHierarchicalLayout; 
import com.mxgraph.model.mxGeometry; 
import com.mxgraph.swing.mxGraphComponent; 
import com.mxgraph.util.mxConstants; 
import com.mxgraph.util.mxPoint; 
import com.mxgraph.util.mxRectangle; 
import com.mxgraph.view.mxGraph; 
import com.mxgraph.layout.hierarchical.mxHierarchicalLayout; 
public class HelloWorld extends JFrame 
{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -2707712944901661771L; 

    public HelloWorld() 
    { 
     super("Hello, puppies!"); 

     mxGraph graph = new mxGraph(); 
     Object parent = graph.getDefaultParent(); 

     graph.getModel().beginUpdate(); 
     try 
     { 
      //Notice this time the parent is the vDogsRoot vertex. 
      //This creates a cell group if I understand correctly. 
      Object vDogsRoot = graph.insertVertex(parent, null, "DOG", 0, 0, 80, 30, ""); 
      Object v2 = graph.insertVertex(vDogsRoot, null, "Shar Pei", 0, 0, 80, 30, ""); 
      Object v3 = graph.insertVertex(vDogsRoot, null, "Pug", 0, 0, 80, 30, ""); 
      Object v4 = graph.insertVertex(vDogsRoot, null, "Cocker Spaniel", 0, 0, 80, 30, ""); 
      Object v5 = graph.insertVertex(vDogsRoot, null, "Pit Bull", 0, 0, 80, 30, ""); 
      Object v6 = graph.insertVertex(vDogsRoot, null, "Chihuahua", 0, 0, 80, 30, ""); 

      graph.insertEdge(parent, null, "", vDogsRoot, v2); 
      graph.insertEdge(parent, null, "", vDogsRoot, v3); 
      graph.insertEdge(parent, null, "", vDogsRoot, v4); 
      graph.insertEdge(parent, null, "", vDogsRoot, v5); 
      graph.insertEdge(parent, null, "", vDogsRoot, v6); 

      mxHierarchicalLayout layout = new mxHierarchicalLayout(graph); 
      layout.setUseBoundingBox(false); 

      layout.execute(vDogsRoot); //apply the layout to the root group node. 
      layout.execute(parent); 
     } 
     finally 
     { 
      graph.getModel().endUpdate(); 
     } 

     mxGraphComponent graphComponent = new mxGraphComponent(graph); 
     getContentPane().add(graphComponent); 
    } 

    public static void main(String[] args) 
    { 
     HelloWorld frame = new HelloWorld(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(400, 320); 
     frame.setVisible(true); 
    } 

} 

는 생산 : (붕괴 버튼을 통지)

enter image description here

어떻게 셀 그룹의 상위 세포 내부되는 것을 정점을 방지합니까? 트리 계층 구조는 유지되지만 접을 수 있기를 원합니다. 셀 그룹을 사용하여 올바른 경로에 있습니까? 내가 뭘 잘못하고 있니?

셀 그룹의 부모에게 (vDogsRoot) 경계를 벗어난 셀을 허용해야한다고 생각하지만 아직 수행 할 방법이 없습니다. 아니면 완전히 잘못된 접근법을 취하고 있습니다. 이것을 달성하는 것은 사소한 일이어야한다고 생각하지만 나는 많은 다른 것들을 시도하고 많은 문서들을 봤지만 아직 성공하지 못했습니다.

업데이트 1 :

그룹이 내가 필요로하는 것이 아닙니다. 난 그냥 지시 트리를 탐색하고 선택한 노드 아래 노드를 표시 토글해야합니다. mxGraph 예제 폴더에 tree.html이라는 자바 스크립트 예제가 있습니다. 이 예제를 자바 스크립트에서 자바로 변환하면됩니다.

답변

0

나는 이것에 대해 어떻게 느끼는지 확실하지 않지만 여기에 해결책이 있습니다. 나는 부분적으로 tree.html example을 자바 스크립트에서 자바로 변환했다. 나는 모든 코드를 Java로 변환하지 않았다. 나는 붕괴 버튼의 위치에 상관하지 않기 때문에 시도조차하지 않았다. 나는 내가 원하는 기능을 얻었다. 나는 그 부분이 유지하는 것이 중요 할 경우 수퍼 메소드가 수행하고있는 몇 가지 코드를 추가했다.

누구든지 사례를 변환하고 나에게 제공하고 싶다면 답장을주는 대신 대답 해 주신 것을 기쁘게 생각합니다. 대답을 얻는 다른 방법 - 내 코드의 버그를 지적하고, 그것을 다소 향상 시키거나 코드를 사용하여 더 나은 접근법을 제공합니다.

package com.mxgraph.examples.swing; 

import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JFrame; 

import com.mxgraph.layout.mxCompactTreeLayout; 
import com.mxgraph.swing.mxGraphComponent; 
import com.mxgraph.util.mxEvent; 
import com.mxgraph.util.mxEventObject; 
import com.mxgraph.util.mxEventSource.mxIEventListener; 
import com.mxgraph.view.mxGraph; 

/** 
* A foldable directed acyclic graph (DAG) where each child has only one parent. AKA a Tree. 
* 
* @author some programmer 
* 
*/ 
class FoldableTree extends mxGraph 
{ 
    /** 
    * Need to add some conditions that will get us the expand/collapse icon on the vertex. 
    */ 
    @Override 
    public boolean isCellFoldable(Object cell, boolean collapse) 
    { 
     //I want to keep the original behavior for groups in case I use a group someday. 
     boolean result = super.isCellFoldable(cell, collapse); 
     if(!result) 
     { 
      //I also want cells with outgoing edges to be foldable... 
      return this.getOutgoingEdges(cell).length > 0; 
     } 
     return result; 
    } 

    /** 
    * Need to define how to fold cells for our DAG. In this case we want to traverse the tree collecting 
    * all child vertices and then hide/show them and their edges as needed. 
    */ 
    @Override 
    public Object[] foldCells(boolean collapse, boolean recurse, Object[] cells, boolean checkFoldable) 
    { 
     //super.foldCells does this so I will too... 
     if(cells == null) 
     { 
      cells = getFoldableCells(getSelectionCells(), collapse); 
     } 

     this.getModel().beginUpdate(); 

     try 
     {   
      toggleSubtree(this, cells[0], !collapse); 
      this.model.setCollapsed(cells[0], collapse); 
      fireEvent(new mxEventObject(mxEvent.FOLD_CELLS, "cells", cells, "collapse", collapse, "recurse", recurse)); 
     } 
     finally 
     { 
      this.getModel().endUpdate(); 
     } 

     return cells; 
    } 

    // Updates the visible state of a given subtree taking into 
    // account the collapsed state of the traversed branches 
    private void toggleSubtree(mxGraph graph, Object cellSelected, boolean show) 
    { 
     List<Object> cellsAffected = new ArrayList<>(); 
     graph.traverse(cellSelected, true, new mxICellVisitor() {     
        @Override 
        public boolean visit(Object vertex, Object edge) { 
         // We do not want to hide/show the vertex that was clicked by the user to do not 
         // add it to the list of cells affected. 
         if(vertex != cellSelected) 
         { 
          cellsAffected.add(vertex); 
         } 

         // Do not stop recursing when vertex is the cell the user clicked. Need to keep 
         // going because this may be an expand. 
         // Do stop recursing when the vertex is already collapsed. 
         return vertex == cellSelected || !graph.isCellCollapsed(vertex); 
        } 
       }); 

     graph.toggleCells(show, cellsAffected.toArray(), true/*includeEdges*/);  
    } 
} 

public class ChampsTree extends JFrame 
{ 
    private static final long serialVersionUID = -2707712944901661771L; 

    public ChampsTree() 
    { 
     super("Hello, World!"); 

     FoldableTree graph = new FoldableTree(); 

     mxCompactTreeLayout layout = new mxCompactTreeLayout(graph, false);   
     layout.setUseBoundingBox(false); 
     layout.setEdgeRouting(false); 
     layout.setLevelDistance(30); 
     layout.setNodeDistance(10); 

     Object parent = graph.getDefaultParent(); 

     graph.getModel().beginUpdate(); 
     try 
     {   
      Object root = graph.insertVertex(parent, "treeRoot", "Root", 0, 0, 60, 40); 

      Object v1 = graph.insertVertex(parent, "v1", "Child 1", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", root, v1); 

      Object v2 = graph.insertVertex(parent, "v2", "Child 2", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", root, v2); 

      Object v3 = graph.insertVertex(parent, "v3", "Child 3", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", root, v3); 

      Object v11 = graph.insertVertex(parent, "v11", "Child 1.1", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", v1, v11); 

      Object v12 = graph.insertVertex(parent, "v12", "Child 1.2", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", v1, v12); 

      Object v21 = graph.insertVertex(parent, "v21", "Child 2.1", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", v2, v21); 

      Object v22 = graph.insertVertex(parent, "v22", "Child 2.2", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", v2, v22); 

      Object v221 = graph.insertVertex(parent, "v221", "Child 2.2.1", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", v22, v221); 

      Object v222 = graph.insertVertex(parent, "v222", "Child 2.2.2", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", v22, v222); 

      Object v31 = graph.insertVertex(parent, "v31", "Child 3.1", 0, 0, 60, 40); 
      graph.insertEdge(parent, null, "", v3, v31);    

      layout.execute(parent);   
     } 
     finally 
     { 
      graph.getModel().endUpdate(); 
     } 

     graph.addListener(mxEvent.FOLD_CELLS, new mxIEventListener() { 

      @Override 
      public void invoke(Object sender, mxEventObject evt) { 
       layout.execute(graph.getDefaultParent()); 
      } 
     }); 

     mxGraphComponent graphComponent = new mxGraphComponent(graph); 

     getContentPane().add(graphComponent); 
    } 

    public static void main(String[] args) 
    { 
     ChampsTree frame = new ChampsTree(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(400, 320); 
     frame.setVisible(true); 
    } 
} 

Fully Expanded

공지 사항 나무가 더 컴팩트 (나머지 노드가 가까워 올) 붕괴하면된다 :

여기 내 자바 코드입니다. 이는 폴드 발생 후 레이아웃을 호출하는 핸들러 때문입니다.내 진짜 나무가 꽤 커지기 때문에 나무의 시각적 복잡성이 줄어 듭니다.

enter image description here

enter image description here

Full Collapsed