I've been using JUNG to visualize some simple graphs, and I'd like to write several of them to a PNG file. Unfortunately, the images often appear to render before the graph is finished painting, meaning that I get incomplete graphs -- that is, graphs where only a hanfdul of edges or nodes are drawn -- about half of the time. Rendering to screen works fine, which is part of why I'm so puzzled. As you'll see below, I tried a couple of workarounds, but they didn't help. It may be useful to know that the basicVisualizationServer I'm using won't paint anything useful to the BufferedImage directly -- I just get a black image when I try that.
Thanks!
public void writeImage(String filename) {
Layout layout = new CircleLayout<V, E>(jungGraph);
layout.setSize(innerSize);
bvs = new BasicVisualizationServer<V,E>(layout);
float strokeWidth = 8f;
bvs.getRenderContext().setVertexShapeTransformer(new ConstantTransformer(new Ellipse2D.Float(-24,-24,48,48)));
bvs.getRenderContext().setArrowDrawPaintTransformer(new ConstantTransformer(Color.black));
bvs.getRenderContext().setEdgeStrokeTransformer(new ConstantTransformer(new BasicStroke(strokeWidth)));
bvs.getRenderContext().setEdgeArrowStrokeTransformer(new ConstantTransformer(new BasicStroke(strokeWidth)));
bvs.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller<E>());
bvs.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<V>());
bvs.setPreferredSize(viewSize);
//int width = bvs.getWidth(); // Always returns zero
int width = viewFrame.getWidth();
//int height = bvs.getHeight(); // Always returns zero
int height = viewFrame.getHeight();
BufferedImage bim = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bim.createGraphics();
viewFrame.paintAll(g);
g.dispose();
//this.viewFrame.paintComponents(g);
//try{Thread.sleep(1000);} catch(Exception e) {throw new RuntimeException(e);} // Sleeping doesn't help.
try {
File f = new File(filename);
ImageIO.write(bim,"png",f);
System.out.println("wrote image for " + jungGraph + " to "+ filename+ ":" + f.toString());
//try{Thread.sleep(500);} catch(Exception e) {throw new RuntimeException(e);} // Doesn't help
} catch (Exception e) {
throw new RuntimeException(e);
}
}
We usually want to save the state of a manipulated graph. We zoom and position the components the way we like and then we make a picture of the container. This can be achieved like this:
Pass the JPanel inside your JScrollPane, or any Component that hosts your JUNG2 graph to ScreenImage.createImage in order to create an image.
Read also other topics of the above mentioned blog :-)
You can also use VisualizationImageServer. It's a subtype of BasicVisualizationServer which adds a getImage method. I have had no trouble with it rendering the graphs properly.
Your code would then be like: