JFreechart Example |
The particular charts do not have replacements available in free charting software like JFreechart currently, and are available only as commercial software. We had purchased the original software and licenses from Rogue Wave, and did not want to purchase new commercial software.
Now to the conundrum. Since Java 1.4, heavyweight AWT and Swing components throw a
HeadlessException
, if you attempt to run them on a headless system.Button
Checkbox
Choice
Dialog
FileDialog
Frame
Label
List
Menu
MenuBar
MenuItem
PopupMenu
Scrollbar
ScrollPane
TextArea
TextField
Window
As you can see from the list, it does not leave much room for the developer to work with in a headless environment. Fair enough, AWT/Swing are GUI environments.
The graphical libraries used to create charts in the case of Rogue Wave and JFreechart generally expect a GUI framework. Rogue Wave is expecting to generate the chart images in a
Window
, or one of its subclasses like Frame
. This can cause an issue as you can see. So I am left with a couple of components that I can use like Component
, Canvas
, and Panel
.You can create a headless environment and check it with the code below.
System.setProperty("java.awt.headless", "true");
boolean headless = GraphicsEnvironment.isHeadless();
System.out.println("Headless: " + headless);
So how do you generate the charts, or create images in general on a headless system. It turns out to be quite simple. Since all components have a
paint(Graphics g)
method, and JFreechart has a createBufferedImage()
method. These turn out to be the keys.Solution
We need to create aBufferedImage
which we can pass to the Component
to paint. Once we create the image to paint to, we simply ask the component to paint it, and use ImageIO
to output our chart.Note: You will need to have the Rogue Wave graphing and gif libraries, or you may comment out those code sections.
NetBeans 6.9 project files: HeadlessAWT.zip
Headless.java
/* * Copyright 2010 Blue Lotus Software. * Copyright 2010 John Yeary. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * under the License. */ package com.bluelotussoftware.graph.headless.example; import java.awt.*; import java.io.*; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.util.Locale; import com.roguewave.chart.awt.datamodels.v2_2.SampleData; import com.roguewave.chart.awt.standard.v2_2.beans.PieChart; import com.roguewave.chart.awt.standard.v2_2.beans.LineChart; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.encoders.ImageFormat; import org.jfree.data.general.DefaultKeyedValuesDataset; import org.jfree.data.general.DefaultPieDataset; /** * * @author John Yeary * @version 1.0 */ public class Headless { private static BufferedImage generateRectangle(Component component, int width, int height) { BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics graphics = bufferedImage.getGraphics(); graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, width, height); graphics.setColor(Color.ORANGE); graphics.fill3DRect(50, 50, 300, 300, true); component.paint(graphics); return bufferedImage; } private static BufferedImage generateRectangle(Component component) { return generateRectangle(component, 400, 400); } private static BufferedImage generateCylinder(int width, int height) { Panel panel = new Panel(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics graphics = image.getGraphics(); graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, width, height); graphics.setColor(Color.ORANGE); graphics.drawOval(100, 100, 50, 75); graphics.fillOval(200, 100, 50, 75); graphics.drawLine(125, 100, 225, 100); graphics.drawLine(125, 175, 225, 175); panel.paint(graphics); return image; } private static boolean save(BufferedImage image, Component component) { boolean success = false; try { ImageIO.write(image, "gif", new FileOutputStream(component.getClass().getSimpleName() + ".gif")); success = true; } catch (FileNotFoundException fnfe) { fnfe.printStackTrace(System.err); } catch (IOException ex) { ex.printStackTrace(System.err); } return success; } /** * @param args the command line arguments */ public static void main(String[] args) throws IOException { System.setProperty("java.awt.headless", "true"); boolean headless = GraphicsEnvironment.isHeadless(); System.out.println("Headless: " + headless); Toolkit tk = Toolkit.getDefaultToolkit(); tk.beep(); BufferedImage bufferedImage = null; boolean success = false; // ---------------------------------------------------------------------------------------------- // Component component = new Component() { private static final long serialVersionUID = 3109256773218160485L; }; Canvas canvas = new Canvas(); Panel panel = new Panel(); // ---------------------------------------------------------------------------------------------- // // Drawing Examples bufferedImage = Headless.generateRectangle(component); success = Headless.save(bufferedImage, component); System.out.println("Created " + component.getClass().getSimpleName() + " : " + success); success = false; bufferedImage = Headless.generateRectangle(canvas); success = Headless.save(bufferedImage, canvas); System.out.println("Created " + canvas.getClass().getSimpleName() + " : " + success); success = false; // bufferedImage = Headless.generateRectangle(panel); // success = Headless.save(bufferedImage, panel); // System.out.println("Created " + panel.getClass().getSimpleName() + " : " + success); // success = false; bufferedImage = Headless.generateCylinder(400, 400); success = Headless.save(bufferedImage, panel); System.out.println("Created " + panel.getClass().getSimpleName() + " : " + success); success = false; // ---------------------------------------------------------------------------------------------- // // Rogue Wave Examples SampleData sd = new SampleData(); LineChart lineChart = new LineChart(); lineChart.setData(sd); PieChart pieChart = new PieChart(); pieChart.setData(sd); // The chart size is required. lineChart.setSize(400, 400); pieChart.setSize(400, 400); bufferedImage = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D) bufferedImage.getGraphics(); lineChart.paint(g); ImageIO.write(bufferedImage, ImageFormat.PNG, new FileOutputStream("LineChart.png")); pieChart.paint(g); ImageIO.write(bufferedImage, ImageFormat.PNG, new FileOutputStream("PieChart.png")); // ---------------------------------------------------------------------------------------------- // // JFreechart Examples DefaultPieDataset dpds = new DefaultKeyedValuesDataset(); dpds.setValue("Java", 60.0); dpds.setValue("C++", 20.0); dpds.setValue("MS Technologies", 10.0); dpds.setValue("Misc.", 10.0); JFreeChart jfc = ChartFactory.createPieChart("Programming Languages", dpds, true, true, Locale.ENGLISH); bufferedImage = jfc.createBufferedImage(400, 400); ImageIO.write(bufferedImage, "gif", new FileOutputStream("jfc-piechart.gif")); } }
Good it's working fine .. thanks
ReplyDeleteCan you tell me where to get the roguewave libraries? Are they availible via maven?
ReplyDeleteThe original Rogue Wave libraries were commercial code from the company of the same name. They no longer have any links to their old products and have moved on to other technologies.
ReplyDelete