ノードの視覚属性の設定は文字列の表示と同じような方法で行います。BasicVisualizationServer<MyNode,MyEdge>オブジェクトのpanelに対して、各ノードと視覚属性を対応付ける写像を設定します。写像はTransformerオブジェクトのtransform()メソッドによって定義します。
ノードから塗り色への写像はTransformer<MyNode,Paint>オブジェクトで定義し、その写像をsetVertexFillPaintTransformer()メソッドで設定します。
1: import java.awt.Color; 2: import java.awt.Dimension; 3: import java.awt.Paint; 4: import java.awt.geom.Point2D; 5: import javax.swing.JFrame; 6: import org.apache.commons.collections15.Transformer; 7: import edu.uci.ics.jung.algorithms.layout.Layout; 8: import edu.uci.ics.jung.algorithms.layout.StaticLayout; 9: import edu.uci.ics.jung.graph.Graph; 10: import edu.uci.ics.jung.graph.UndirectedSparseGraph; 11: import edu.uci.ics.jung.visualization.BasicVisualizationServer; 12: public class Sample5a { 13: public static void main(String[] args) { 14: Graph<MyNode,MyEdge> graph = new UndirectedSparseGraph<MyNode,MyEdge>(); 15: MyNode n1 = new MyNode("n1"); 16: MyNode n2 = new MyNode("n2"); 17: MyNode n3 = new MyNode("n3"); 18: graph.addEdge(new MyEdge("e1"), n1, n2); 19: graph.addEdge(new MyEdge("e2"), n2, n3); 20: Layout<MyNode,MyEdge> layout = new StaticLayout<MyNode,MyEdge>(graph); 21: layout.setLocation(n1, new Point2D.Double(100, 100)); 22: layout.setLocation(n2, new Point2D.Double(200, 100)); 23: layout.setLocation(n3, new Point2D.Double(150, 200)); 24: BasicVisualizationServer<MyNode,MyEdge> panel = new BasicVisualizationServer<MyNode,MyEdge>(layout, new Dimension(300, 300)); 25: Transformer<MyNode,Paint> nodeFillColor = new Transformer<MyNode,Paint>() { 26: @Override 27: public Paint transform(MyNode n) { 28: return Color.BLUE; 29: } 30: }; 31: panel.getRenderContext().setVertexFillPaintTransformer(nodeFillColor); 32: JFrame frame = new JFrame("Graph View: Blue Nodes"); 33: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 34: frame.getContentPane().add(panel); 35: frame.pack(); 36: frame.setVisible(true); 37: } 38: }
ノードから色への写像は、25行目から30行目で、Transformer<MyNode,Paint>オブジェクトのtransform()メソッドによって定義しています。ここでは28行目で、Color.BLUE(青色)を指定しています。定義した写像nodeFillColorを、31行目で、BasicVisualizationServer<MyNode,MyEdge>オブジェクトのpanelに対して、setVertexFillPaintTransformer()メソッドで設定しています。
上のプログラムを実行するとするとノードが下のように描かれます。
Transformer<MyNode,Paint>オブジェクトのtransform()メソッドはMyNodeを引数として取るので、ノード毎に色を変えることもできます。
25: Transformer<MyNode,Paint> nodeFillColor = new Transformer<MyNode,Paint>() { 26: @Override 27: public Paint transform(MyNode n) { 28: int id = Integer.parseInt(n.label.substring(1)); 29: return new Color(Color.HSBtoRGB(id / 3f, 0.7f, 1.0f)); 30: } 31: };
28行目でノードに指定された文字列から整数(「n1」の場合には1)を取り出しています。29行目では、取り出した整数を(ここではノード数が3なので)3で割ってHue(色相)のパラメータとし、色空間HSBからRGBに変更して、ノードnの色としています。28行目と29行目は、若干面倒なことをしていますが、その方法自体は重要ではありません(分らなければ無理して理解する必要はありません)。重要なことはノードnに対して適当なColorオブジェクトを返すようにtransform()メソッドを適切に定義することです。
上のように改造したプログラムを実行するとするとノードが下のように描かれます。
ノード内部を塗り潰す色だけでなく、輪郭線の色を指定することもできます。輪郭線の色はsetVertexDrawPaintTransformer()メソッドで設定します。次の例では境界線を緑にしています。
25: Transformer<MyNode,Paint> nodeDrawColor = new Transformer<MyNode,Paint>() { 26: @Override 27: public Paint transform(MyNode n) { 28: return Color.GREEN; 29: } 30: }; 31: panel.getRenderContext().setVertexDrawPaintTransformer(nodeDrawColor);
Transformer<MyNode,Paint>クラスの定義は塗り潰し色の指定と同様です。ここではtransform()メソッドは単にColor.GREENを返しています。こうして定義したnodeDrawColorをsetVertexDrawPaintTransformer()メソッドで指定します。
上のように改造したプログラムを実行するとすると下のようにノードが描かれます。画面では分り難いかも知れませんが、ノードの輪郭線が緑になっています。
少し違う方法を使うと、ノードの塗り色にグラデーションを指定することもできます。
24: panel.getRenderer().setVertexRenderer( new GradientVertexRenderer<MyNode,MyEdge>( Color.YELLOW, Color.BLUE, false));
上のように設定すると下のようなノードが描かれます。
形状の設定も色と同様の方法で行います。ノードから形状への写像はTransformer<MyNode,Shape>オブジェクトで定義し、その写像をsetVertexShapeTransformer()メソッドで設定します。
25: Transformer<MyNode,Shape> nodeShapeTransformer = new Transformer<MyNode,Shape>() { 26: @Override 27: public Shape transform(MyNode n) { 28: return new Rectangle(-15, -10, 30, 20); 29: } 30: }; 31: panel.getRenderContext().setVertexShapeTransformer(nodeShapeTransformer);
ノードの形状の定義は、25行目から30行目で、Transformer<MyNode,Shape>オブジェクトのtransform()メソッドによって定義しています。エッジは原点をつなぐように描かれるので、原点が中心になるようにノードの座標を指定すると良いでしょう。ここでは、(-15, -10)を左上の点とする横30、縦20の長方形(Rectangle)を指定しています。31行目でノードの形状の定義nodeShapeTransformerを指定しています。
上のプログラムを実行するとすると下のようなウィンドウが現われます。
エッジの色の設定もノードと同様の方法で行います。エッジから色への写像はTransformer<MyEdge,Color>オブジェクトで定義し、その写像をsetEdgeDrawPaintTransformer()メソッドで設定します。
25: Transformer<MyEdge, Paint> edgeColor = new Transformer<MyEdge, Paint>() { 26: @Override 27: public Paint transform(MyEdge e) { 28: return Color.BLUE; 29: } 30: }; 31: panel.getRenderContext().setEdgeDrawPaintTransformer(edgeColor);
上のように設定すると下のようにエッジが描かれます。
エッジの形状の設定はsetEdgeShapeTransformer()メソッドで行います。たとえば、エッジを直線分(Line)で表すには下のようにします。
23: panel.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<MyNode,MyEdge>());
上のように設定すると下のようにエッジが描かれます。
直線分以外にも、以下のような形状が用意されています。
エッジの太さの設定は、エッジに対してStrokeオブジェクトを指定することで行います。エッジからStrokeへの写像はTransformer<MyEdge,Stroke>オブジェクトで定義し、その写像をsetEdgeStrokeTransformer()メソッドで設定します。
25: final Stroke edgeStroke = new BasicStroke(10.0f); 26: Transformer<MyEdge, Stroke> edgeStrokeTransformer = new Transformer<MyEdge, Stroke>() { 27: @Override 28: public Stroke transform(MyEdge e) { 29: return edgeStroke; 30: } 31: }; 32: panel.getRenderContext().setEdgeStrokeTransformer(edgeStrokeTransformer);
上のように設定すると下のようにエッジが描かれます。
エッジに対応するStrokeを変更することで、太さだけでなく線種も設定できます。
25: float dash[] = {5f}; 26: final Stroke edgeStroke = new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f); 27: Transformer<MyEdge, Stroke> edgeStrokeTransformer = new Transformer<MyEdge, Stroke>() { 28: @Override 29: public Stroke transform(MyEdge e) { 30: return edgeStroke; 31: } 32: }; 33: panel.getRenderContext().setEdgeStrokeTransformer(edgeStrokeTransformer);
上のように設定すると下のようにエッジが描かれます。
配列dash[]の値によって破線のパターンを変更できます。たとえばdash[] = {10f, 3f, 3f, 3f};とすると一点鎖線を描くことができます。その他、下のようなパターンも試してみて下さい。