Java 如何使用JUNG2绘制相同的边名称

Java 如何使用JUNG2绘制相同的边名称,java,jung2,Java,Jung2,我正在做JUNG2绘制网络拓扑的项目,现在发现JUNG2无法在不同的顶点上绘制相同的边(名称)。报告如下: Exception in thread "main" java.lang.IllegalArgumentException: edge GigabitEthernet0/3<--->GigabitEthernet0/0/0/0 already exists in this graph with endpoints <HKBR1, HKBR3> and cannot

我正在做JUNG2绘制网络拓扑的项目,现在发现JUNG2无法在不同的顶点上绘制相同的边(名称)。报告如下:

Exception in thread "main" java.lang.IllegalArgumentException: edge GigabitEthernet0/3<--->GigabitEthernet0/0/0/0 already exists in this graph with endpoints <HKBR1, HKBR3> and cannot be added with endpoints <HKBR2, HKBR4>
at edu.uci.ics.jung.graph.AbstractGraph.getValidatedEndpoints(AbstractGraph.java:93)
at edu.uci.ics.jung.graph.SparseMultigraph.addEdge(SparseMultigraph.java:123)
at edu.uci.ics.jung.graph.AbstractGraph.addEdge(AbstractGraph.java:60)
at pkg.DrawnTopology.DrawnTopology(DrawnTopology.java:45)
at pkg.ReadLine.main(ReadLine.java:85)
线程“main”java.lang.IllegalArgumentException中的异常:边缘GigabitEthernet0/3GigabitEthernet0/0/0已存在于此具有端点的图形中,无法与端点一起添加
位于edu.uci.ics.jung.graph.AbstractGraph.GetValidatedPoints(AbstractGraph.java:93)
位于edu.uci.ics.jung.graph.sparsemultraph.addEdge(sparsemultraph.java:123)
位于edu.uci.ics.jung.graph.AbstractGraph.addEdge(AbstractGraph.java:60)
在pkg.DrawnTopology.DrawnTopology(DrawnTopology.java:45)
位于pkg.ReadLine.main(ReadLine.java:85)

我将所有边和顶点存储到二维数组中。二维数组数据从不同的文件中学习,因此数据是动态的。由于网络拓扑可能具有相同的边名称,因此如何解决此问题?

从技术上讲,边名称必须是唯一的,但您可以操纵图形中显示的内容。要获得边的唯一名称,我对边的名称使用以下模式:fromVertex\u edgeName\u toVertex

然后需要一个
EdgeLabelTransformer

private class EdgeLabelTransformer<V> implements Transformer<V, String> {

    @Override
    public String transform(V v) {
        return v.toString().substring(v.toString().indexOf("_") + 1, v.toString().lastIndexOf("_"));
    }
}

这个问题显然缺乏细节,但从描述和错误信息中,我们可能可以猜出这里出了什么问题:

您的图形可能被定义为
图形

它可能是
图形
的一个子类,顶点类型无关紧要。关键的一点是边缘类型是
String

您正在尝试向图形中添加边,如下所示:

visualViewer.getRenderContext().setEdgeLabelTransformer(new EdgeLabelTransformer<String>());
g.addEdge("edge0", v0, v1);
g.addEdge("edge0", v2, v3);
这将导致错误,因为边缘
“edge0”
存在两次。(这是有意义的。否则:当您向图形询问
“edge0”
的端点时,会发生什么?它是否返回
v0、v1
v2、v3
?它只是模棱两可)

(请注意,这不仅仅是边类型为
字符串
时的情况。任何边类型都会发生这种情况,只要两条边彼此
相等

这里一个简单的解决方案是引入一个专门的
Edge
类来包装字符串:

class Edge
{
    private final String name;

    Edge(String name)
    {
        this.name = name;
    }

    @Override
    public String toString()
    {
        return name;
    }
}
此类未重写其
equals
方法。因此,即使字符串相等,这种类型的两个对象也将不相等:

Edge e0 = new Edge("edge0");
Edge e1 = new Edge("edge0");
System.out.println(e0.equals(e1)); // prints "false"
然后,边标签可以是这些边的
toString
表示,返回原始字符串

例如:

import javax.swing.JFrame;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationViewer;

class Edge
{
    private final String name;

    Edge(String name)
    {
        this.name = name;
    }

    @Override
    public String toString()
    {
        return name;
    }
}

public class JungDuplicateEdgesTest
{
    public static void main(String[] args)
    {
        JFrame jf = new JFrame();
        final Graph<String, Edge> g = getGraph();
        VisualizationViewer<String, Edge> vv = 
            new VisualizationViewer<String, Edge>(
                new FRLayout<String, Edge>(g));

        class EdgeLabelTransformer implements Transformer<Edge, String>
        {
            @Override
            public String transform(Edge edge)
            {
                return edge.toString();
            }
        }
        vv.getRenderContext().setEdgeLabelTransformer(
            new EdgeLabelTransformer());

        jf.getContentPane().add(vv);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.pack();
        jf.setVisible(true);
    }

    public static Graph<String, Edge> getGraph()
    {
        Graph<String, Edge> g = new DirectedSparseGraph<String, Edge>();
        g.addVertex("v0");
        g.addVertex("v1");
        g.addEdge(new Edge("e0"), "v0", "v1");
        g.addEdge(new Edge("e0"), "v1", "v0");
        return g;
    }
}
import javax.swing.JFrame;
导入org.apache.commons.collections15.Transformer;
导入edu.uci.ics.jung.algorithms.layout.FRLayout;
导入edu.uci.ics.jung.graph.DirectedSparseGraph;
导入edu.uci.ics.jung.graph.graph;
导入edu.uci.ics.jung.visualization.VisualizationViewer;
阶级边缘
{
私有最终字符串名;
边缘(字符串名称)
{
this.name=名称;
}
@凌驾
公共字符串toString()
{
返回名称;
}
}
公共类
{
公共静态void main(字符串[]args)
{
JFrame jf=新JFrame();
最终图形g=getGraph();
VisualizationViewer vv=
新的VisualizationViewer(
新FRG布局(g);
类EdgeLabelTransformer实现了Transformer
{
@凌驾
公共字符串转换(边)
{
返回edge.toString();
}
}
vv.getRenderContext().setEdgeLabelTransformer(
新EdgeLabelTransformer());
jf.getContentPane().add(vv);
jf.setDefaultCloseOperation(JFrame.EXIT\u ON\u CLOSE);
jf.pack();
jf.setVisible(真);
}
公共静态图getGraph()
{
图g=新的DirectedSparseGraph();
g、 addVertex(“v0”);
g、 addVertex(“v1”);
g、 附录(新边缘(“e0”)、“v0”、“v1”);
g、 附录(新边缘(“e0”)、“v1”、“v0”);
返回g;
}
}


旁注:对于某些应用程序,将边的顶点存储在
edge
类中也是有意义的。然后可以实现
equals
hashCode
方法,使您可以在两条边具有相同顶点时将它们视为相等

请提供最少的代码来重现问题。@ace,对不起,我以后会注意,当Marco13响应时,简单的代码可以重现报警:
g.addEdge(“edge0”,v0,v1)
g.addEdge(“edge0”,v2,v3)Marco13,非常感谢您的友好回复!!!根据您的代码,JUNG2应该使用物理地址检查一条边是否等于另一条边,因此使用新对象并通过toString()返回相同的边名称,尽管两条边具有相同的名称,但物理地址不同(在您测试时)!非常酷的解决方案!我将更改我的代码。由于我是排名第15的声誉,所以无法投票支持您的答案…嗨,Marco13,还有一个问题,如何将二维数组从其他类转移到getGraph()?例如:
g.addEdge(测试[2][x],测试[0][x],测试[1][x])@frank它实际上没有使用“物理地址”。它使用类的
hashCode
equals
方法。(但如果这些方法没有被覆盖,那么可以想象它们使用某种“物理地址”)。第二个问题:这取决于图形的构造方式和位置。您已经在某个地方创建了图形。毫无疑问,您不必做太多更改—只需更改edge type参数,而不是使用旧的
g.add(test[2][x],…)
编写
g.add(new edge(test[2][x]),…)
。嗨,莫霍,谢谢您的回复!由于边缘名称现在太长(例如GigabitEthernet0/3GigabitEthernet0/0/0/0),所以在边缘名称中添加其他字符串不是一个好方法。