ノードの文字列表現、つまりtoStringメソッドで返される文字列をラベルとしてノードの側に表示しましょう。Sample3a.scalaを下のように改造します。
1: import swing._ 2: import java.util._ 3: import java.awt.Dimension 4: import java.awt.geom.Point2D 5: import edu.uci.ics.jung.algorithms.layout.{Layout,StaticLayout} 6: import edu.uci.ics.jung.graph.{Graph,UndirectedSparseGraph} 7: import edu.uci.ics.jung.visualization.BasicVisualizationServer 8: import edu.uci.ics.jung.visualization.decorators.ToStringLabeller 9: object Sample4a extends SimpleSwingApplication { 10: def top = new MainFrame { 11: title = "Graph View: Manual Layout" 12: val (graph, layout) = createGraph 13: val panel = new BasicVisualizationServer[MyNode,MyEdge](layout, new Dimension(300, 300)) 14: panel.getRenderContext.setVertexLabelTransformer(new ToStringLabeller[MyNode]) 15: contents = Component.wrap(panel) 16: } 17: def createGraph: Tuple2[Graph[MyNode,MyEdge],Layout[MyNode,MyEdge]] = { 18: val graph: Graph[MyNode,MyEdge] = new UndirectedSparseGraph[MyNode,MyEdge]() 19: val n1 = new MyNode("n1") 20: val n2 = new MyNode("n2") 21: val n3 = new MyNode("n3") 22: graph.addVertex(n1) 23: graph.addVertex(n2) 24: graph.addVertex(n3) 25: graph.addEdge(new MyEdge("e1"), n1, n2) 26: graph.addEdge(new MyEdge("e2"), n2, n3) 27: val layout: Layout[MyNode,MyEdge] = new StaticLayout[MyNode,MyEdge](graph) 28: layout.setLocation(n1, new Point2D.Double(100, 100)) 29: layout.setLocation(n2, new Point2D.Double(200, 100)) 30: layout.setLocation(n3, new Point2D.Double(150, 200)) 31: (graph, layout) 32: } 33: }
14行目がノードに文字列を表示するように指定している行で、BasicVisualizationServer[MyNode,MyEdge]型のpanelに対して、ラベル付けの方法を設定しています。ToStringLabeller[V]クラスは、Transformer[V,String]トレイトを拡張したクラスで、V型のオブジェクトに対して、その文字列表現を対応付けます。MyNodeクラスではコンストラクタで設定した文字列labelがtoStringメソッドで返されるので、labelが「n1」のノードには文字列「n1」がそのまま表示されます。
上のプログラムを実行するとすると下のように表示されます。
ノードの文字列表現とは別の独自に定義した文字列をラベルとして表示しましょう。Sample4a.scalaを下のように改造します。
14: val labeller = new Transformer[MyNode,String] { 15: override def transform(n: MyNode): String = "node: " + n.label 16: } 17: panel.getRenderContext.setVertexLabelTransformer(labeller);
ラベル付けの方法は、14行目から16行目で、Transformer[MyNode,String]型のオブジェクトのtransform()メソッドによって定義しています。ここでは15行目にあるように、「"node: " + n.label」として定義しています。つまりlabelが「n1」のノードには文字列「node: n1」が表示されます。17行目がノードに文字列を表示するように指定している行で、BasicVisualizationServer[MyNode,MyEdge]型のpanelに対して、ラベル付けの方法を定義したlabellerを設定しています。
上のプログラムを実行するとすると下のようなウィンドウが現われます。
Transformerはパッケージorg.apache.commons.collections15で定義されているインタフェースで、JUNG2.0で定義されているものではありません。
JUNG2.0では、ラベル表示だけでなく、グラフのノードやエッジに対する属性値を定義するためにTransformerを利用します。そのため、上のような定義を至る所で行います。
上の例ではノードのラベルがノードの右下に表示されています。ラベルの位置を変更するには、下のような行を適当な場所に追加します。
panel.getRenderer.getVertexLabelRenderer.setPosition(Position.CNTR)
この行を追加すると下のような表示になります。つまりラベルがノードの中心に表示されます。下の例では、ラベルが短いので、ノードの内側に納まっていますが、ラベルが長い場合には、ノードの左右にはみ出ます。
位置はCNTR(中央)以外に、上から時計回りに、N、NE、E、SE、S、SW、W、NWの8方向が選択できます。たとえばPosition.Nを指定すると、ノードの上部に配置されます。デフォルトはSEで、右下です。これら以外にAUTOも指定できます。自動で「うまく」配置してくれるようです。たとえば、同じグラフにPosition.AUTOを指定すると下のようになります。
エッジに文字列を表示する方法も、ノードと同様です。BasicVisualizationServer[MyNode,MyEdge]型のpanelに対して、setEdgeLabelTransformer()メソッドで、エッジのラベル付けの方法を定義したオブジェクトを設定します。
panel.getRenderContext.setEdgeLabelTransformer(new ToStringLabeller[MyEdge])
エッジのラベルは下のように表示されます。
独自に定義した文字列をラベルとして表示する方法も、ノードと同様です。
14: val labeller = new Transformer[MyEdge,String] { 15: override def transform(e: MyEdge): String = "edge: " + e.label 16: } 17: panel.getRenderContext.setEdgeLabelTransformer(labeller)
エッジのラベルは下のように表示されます。