2012-04-06 45 views
3

我正在開發Java應用程序,並且正在使用JUNG庫。 在我的應用程序首先創建一個DelegateTree並繪製到屏幕上:JUNG:在繪製它之後向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

開始只有根(Outlook)中,用不同的邊緣(晴天,陰天,雨天)將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個不同的邊緣(Outlook和葉)。我猜你正在做這個(或節點和邊緣情況下,等效):

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

在這種情況下,作爲JUNG圖形保持節點的唯一性,你最終只有兩個節點,和3層不同的邊緣它們之間。當JUNG試圖顯示這個圖表時,您會看到兩個節點和3個重疊的邊緣,就像您使用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()將'方法呢,就是看着我的節點對象是否有孩子,如果是的話,爲每個孩子不同的邊緣('新的邊緣(...)'),指向從父節點到子節點,然後遞歸調用'a ddChildren()'方法對每個孩子。 我添加的每個節點和邊都是新的且不同的對象。當我使用現有的樹並調用generateTree()方法時,它很好地繪製我的樹,只要我想要。當我在第一次繪製節點後添加節點時,它不起作用。 – dylan202 2012-04-06 12:37:06

+0

我看了一下TreeLayout類,並且有一個小錯誤,它可以防止在創建新節點時更新節點位置。看到我更新的初步答案。 – ecniv 2012-04-06 15:10:59

+0

非常感謝!增加這個新班級就像一個魅力。 – dylan202 2012-04-06 17:51:57

相關問題