Java 如何使用JUNG2绘制相同的边名称
我正在做JUNG2绘制网络拓扑的项目,现在发现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
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),所以在边缘名称中添加其他字符串不是一个好方法。