writing JUNG graphs to images: can't reliably render complete graph
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(Co开发者_运维问答lor.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);
}
}
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:
public void writeImage(String filename) {
Layout layout = new CircleLayout<V, E>(jungGraph);
layout.setSize(innerSize);
bvs = new VisualizationImageServer<V,E>(layout);
// [...]
BufferedImage image = (BufferedImage)bvs.getImage();
}
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:
- Get the ScreenImage Class from the excellent Rob Camick's blog
Pass the JPanel inside your JScrollPane, or any Component that hosts your JUNG2 graph to ScreenImage.createImage in order to create an image.
private void writeToImageFile(String imageFileName) { BufferedImage bufImage = ScreenImage.createImage((JComponent) jPanel1); try { File outFile = new File(imageFileName); ImageIO.write(bufImage, "png", outFile); System.out.println("wrote image to " + imageFileName); } catch (Exception e) { System.out.println("writeToImageFile(): " + e.getMessage()); } }
Read also other topics of the above mentioned blog :-)
精彩评论