3

私はJavaアプリケーションを開発していて、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つの子(Leaf、Leaf、Leaf)を追加した後、それらは互いに重なり合って表示されます。

編集:これは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);
}
4

1 に答える 1

3

新しいエッジの追加を担当するメソッドを投稿すると、ここで役立ちます:)

しかし一見すると、同じ 2 つのノード (OUTLOOK と Leaf) の間に 3 つの異なるエッジを追加しているように見えます。私はあなたがこれを行っていると推測しています(またはNodeおよびEdgeインスタンスと同等のもの):

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

この場合、JUNG グラフはノードの単一性を維持するため、ノードは 2 つしかなく、それらの間には 3 つの異なるエッジがあります。JUNG がこのグラフを表示しようとすると、EdgeShape.Line を使用したため、2 つのノードと 3 つの重なり合うエッジが表示されます。

本来の目的が 2 つのノード間に 3 つの異なるエッジを設定することであった場合は、異なるエッジ形状を使用してオーバーラップを回避し、より良いレンダリングを取得してみてください (例: EdgeShape.BentLine など)。

3 つの異なるノードが必要な場合は、3 つの異なる名前、または等しくない3 つの異なる Node インスタンスを使用する必要があります。

幸運を :)

編集

あなたのコメントに続いて、私は 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();
于 2012-04-06T10:05:49.587 に答える