Introduction:

Welcome to the second JUNG Tutorial developed by Game2Learn, a member of UNC-Charlotte’s Games + Learning Laboratory. This time we will address the issue of Rendering Icons on Top of Shapes as a vertex in JUNG. So the problem is, you want to have a beautiful shaped vertices, but in addition you want to load some type of image as well inside, next to, or on top of that shape.

The desired goal can be seen below, we have square vertices with colors, we have icons, a O an X and a Game2Learn logo, and we want to print both. The solution we present here, in this tutorial, is to change the vertex render-er, which allows us to achieve the desired results of submitting both a vertexShapeTransformer and a vertexIconTransformer, and have both drawn, which is not possible with the default vertex renderer.

Check here to download the MultiVertexRenderer and associated demo.

A graph with a vertex transformer applied.

A graph with an Icon Transformer applied.

A graph with a MultiVertex Renderer being used by the visualization viewer which lets both the Icon Transformer and the Vertex Transformer get called.

Alternatives:

In the JUNG forums, there are a few proposed solutions which involve making a new kind of Icon-class which extends shape. Then create your icon which would be our images above, (O, X, or Logo) and add the icon on top of the vertex shape with LayeredIcon. This transformer is then given to the VertexIconTransformer. Though this approach may work we found it more complicated than a much faster change which can be made by creating a new VertexRenderer.

Our Solution – A New Vertex Renderer:

We suggest making a new class for the VertexRenderer, which seems easier and faster. So create a new class defined as:

public class MultiVertexRenderer<V,E> implements Renderer.Vertex<V,E>

This new class will pretty much be an exact copy of the BasicVertexRenderer.java class found in the JUNG library. But we will make one important change.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
At line 67: <strong>BasicVertexRenderer</strong>
if (vertexHit)
{
   if(rc.getVertexIconTransformer() != null)
   {
      Icon icon = rc.getVertexIconTransformer().transform(v);
      if(icon != null)
      {
         g.draw(icon, rc.getScreenDevice(), shape, (int)x, (int)y);
      }
      else
      {
         paintShapeForVertex(rc, v, shape);
      }
   }
   else
   {
      paintShapeForVertex(rc, v, shape);
   }
}
<strong>Our Code:</strong>
Icon icon = rc.getVertexIconTransformer().transform(v);
if(icon != null)
{
   paintShapeForVertex(rc, v, shape); //<strong>We added this line!</strong>
   g.draw(icon, rc.getScreenDevice(), shape, (int)x, (int)y);
}
else
{

That way we can draw both the VertexIconTransformer and the VertexShapeTransformer when our vertices are drawn. The end result is that we have our image inside a vertex. Naturally you have to replace the vertex renderer of your visualizaitonviewer as well.

vv.getRenderer().setVertexRenderer(new MultiVertexRenderer<node,edge>());

The line above sets the vertex renderer to be our new version of the renderer as opposed to the basic one which is run by default.

Conclusion:

The way the original basicVertexRenderer was written is a case of either or, meaning that two vertices (Icon, and Shape) are mutually exclusive, by just adjusting how the if statement works, it is possible to make a composite image for each vertex, where it draws both, one on top of the other. Feel free to download the demo code linked above at the top of the article.

Limitations:

One issue regarding this approach is that it can be difficult to allow multiple icons on a single vertex, because the VertexIconTransformer returns a single Icon. One option which could be possible if you have a small set of icons, is to generate a set of composite images. Imagine each of our vertices can have it’s icon, either the O the X or the logo, as well as star. The composite images, would include each icon with the star pasted on top of it, making our image list have 6 images rather than just the 3 it currently has. Then in the VertexIconTransformer, we have some logical checks for when we should return the image with the star on it or the standard icon.