2012-04-06 1 views
3

Java 응용 프로그램을 개발 중이며 JUNG 라이브러리를 사용하고 있습니다. 내 응용 프로그램에서 나는 먼저 DelegateTree을 만들고 화면에 그릴 :정 : 그려 준 후 DelegateTree에 어린이 추가

public static GraphZoomScrollPane generateTree(Tree tree, 
    GraphicalUserInterface gui) { 

    /* Create a new tree */ 
    edu.uci.ics.jung.graph.Tree<Node, Edge> graphTree = new DelegateTree<Node, Edge>(); 

    /* Add all nodes and vertices to the tree */ 
    graphTree.addVertex(tree.getRoot()); 
    addChildren(tree.getRoot(), graphTree); 

    /* Create the visualization */ 
    TreeLayout<Node, Edge> treeLayout = new TreeLayout<Node, Edge>(graphTree); 
    VisualizationViewer<Node, Edge> vv = new VisualizationViewer<Node, Edge>(treeLayout); 
    vv.setBackground(Color.WHITE); 
    vv.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller<Edge>()); 
    vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<Node, Edge>()); 
    vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Node>()); 
    vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.S); 

    vv.addGraphMouseListener(new ClickNode(gui, vv)); 
    final DefaultModalGraphMouse<Node, Edge> graphMouse = new DefaultModalGraphMouse<Node, Edge>(); 
    graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); 
    vv.setGraphMouse(graphMouse); 

    return new GraphZoomScrollPane(vv); 
} 

이후 사용자가 내 나무의 잎에 새로운 아이를 추가 할 수 있습니다. 난 그냥

graphTree.addEdge(edge, parent, child); 

을 다음 VisualizationViewer을 다시 그릴 때, 시각화는 '나무'구조를 잃었다. 단지 부모를 어딘가에 추가하고 다른 모든 하위를 그 위에 추가합니다.

트리의 잎에 아이들을 동적으로 추가하는 더 좋은 방법이 있습니까? 아니면 다시 그리기를 위해 vv.repaint() 대신 다른 것을 사용해야합니까?

도움이 될만한 의견이 있습니다.

무슨의 예 :

http://www.dylankiss.be/JUNGExample.PNG

다른 가장자리 (써니, 흐린, 비오는)로 3 명 (잎, 잎, 잎)을 추가 한 후, 바로 루트 (전망)을 시작으로, 그들은 단지 서로의 위에 나타납니다.

편집 : 이것은 addChildren() 방법입니다.

private static void addChildren(Node node, edu.uci.ics.jung.graph.Tree<Node, Edge> tree) { 
    for (int i = 0; i < node.getChildren().size(); i++) { 
     tree.addEdge(new Edge(node.getChildren().get(i).getParentValue()), node, node.getChildren().get(i)); 
     addChildren(node.getChildren().get(i), tree); 
    } 
} 

편집 2 : 이것은 트리에 새로운 아이를 추가가 AWT의의 ActionListener의 일부입니다. 여기에 도움이 될 것이다 :

하지만 먼저 눈에 새로운 가장자리를 추가하는 담당하는 방법을 게시

while (there are still edges to be added) { 
    value = name of new edge; 
    child = new Node(this.m_node, value); 
    this.m_node.addChild(child); 
    graphTree.addEdge(new Edge(value), this.m_node, child); 
} 

답변

3

, 당신이 (같은 두 노드 사이의 전망과 잎을 3 개 개의 모서리를 추가하는 것 같다). 정 그래프 노드의 유니시티을 유지, 당신은 단지 두 개의 노드, 3 가지 가장자리 결국,이 경우

graphTree.addChild("sunny", "OUTLOOK", "Leaf"); 
graphTree.addChild("overcast", "OUTLOOK", "Leaf"); 
graphTree.addChild("rainy", "OUTLOOK", "Leaf"); 

: 나는 당신이이 일을하는 추측 (또는 노드와 엣지 경우와 동일)하고있어 그들 사이에. JUNG가이 그래프를 표시하려고 할 때 EdgeShape.Line을 사용할 때 두 개의 노드와 세 개의 겹치는 모서리를 갖게됩니다.

실제로 두 노드 사이에 3 개의 다른 가장자리를 설정하려는 경우 겹치는 것을 방지하기 위해 다른 가장자리 모양을 사용해보십시오. EdgeShape.BentLine 또는 그와 같은.

3 개의 다른 노드를 원하면이 아닌 3 개의 다른 노드 인스턴스 또는 3 개의 다른 노드 인스턴스 을 사용해야합니다.

행운을 빕니다 :)

편집 :

귀하의 의견에 따라, 나는 TreeLayout 소스를 살펴했다, 그것은 불가능 동적으로 레이아웃을 업데이트 할 수있는 작은 문제가 있습니다.

는 문제를 해결하는 대신이 클래스를 사용하려면 각각의 수정을 위해 다시 칠 수 당신은 또한 레이아웃을 업데이트하려면 다음을 추가해야합니다

import edu.uci.ics.jung.algorithms.layout.TreeLayout; 
import java.awt.Point; 
import java.util.Collection; 

import edu.uci.ics.jung.graph.Forest; 
import edu.uci.ics.jung.graph.util.TreeUtils; 

public class DynamicTreeLayout<V, E> 
    extends TreeLayout<V, E> 
{ 
public DynamicTreeLayout(Forest<V, E> g) { 
    this(g, DEFAULT_DISTX, DEFAULT_DISTY); 
} 

public DynamicTreeLayout(Forest<V, E> g, int distx) { 
    this(g, distx, DEFAULT_DISTY); 
} 

public DynamicTreeLayout(Forest<V, E> g, int distx, int disty) { 
    super(g, distx, disty); 
} 

protected void buildTree() { 
    alreadyDone.clear(); // This was missing and prevented the layout to update positions 

    this.m_currentPoint = new Point(20, 20); 
    Collection<V> roots = TreeUtils.getRoots(graph); 
    if (roots.size() > 0 && graph != null) { 
     calculateDimensionX(roots); 
     for (V v : roots) { 
      calculateDimensionX(v); 
      m_currentPoint.x += this.basePositions.get(v)/2 + this.distX; 
      buildTree(v, this.m_currentPoint.x); 
     } 
    } 
} 

private int calculateDimensionX(V v) { 
    int localSize = 0; 
    int childrenNum = graph.getSuccessors(v).size(); 

    if (childrenNum != 0) { 
     for (V element : graph.getSuccessors(v)) { 
      localSize += calculateDimensionX(element) + distX; 
     } 
    } 
    localSize = Math.max(0, localSize - distX); 
    basePositions.put(v, localSize); 

    return localSize; 
} 

private int calculateDimensionX(Collection<V> roots) { 
    int localSize = 0; 
    for (V v : roots) { 
     int childrenNum = graph.getSuccessors(v).size(); 

     if (childrenNum != 0) { 
      for (V element : graph.getSuccessors(v)) { 
       localSize += calculateDimensionX(element) + distX; 
      } 
     } 
     localSize = Math.max(0, localSize - distX); 
     basePositions.put(v, localSize); 
    } 

    return localSize; 
} 
} 

및 뷰어를하여 그래프 :

layout.setGraph(g); 
vv.repaint(); 
+0

내 AddChildren() 메소드가하는 일은 내 Node 객체에 자식이 있는지 여부를 확인하고, 그렇다면 각 자식에 대해 뚜렷한 가장자리 ('new Edge (...) 부모 노드에서 자식 노드로, 그리고 재귀 적으로'a ddChildren()'메소드를 호출합니다. 모든 노드와 에지 추가는 모두 새롭고 별개의 개체입니다. 기존 트리를 사용하고'generateTree()'메소드를 호출하면, 원하는대로 내 트리를 멋지게 그립니다. 노드를 처음 추가 한 후에 노드를 추가하면 작동하지 않습니다. – dylan202

+0

TreeLayout 클래스를 살펴 봤습니다. 새 노드를 만들 때 노드 위치를 업데이트하지 못하도록하는 작은 버그가 있습니다. 내 업데이트 된 초기 답변을 참조하십시오. – ecniv

+0

정말 고마워요! 이 새로운 클래스를 추가하는 것은 매력처럼 작동했습니다. – dylan202