I recently was given a copy of ChartFX for Java to evaluate as a charting solution for a Java project. After using it for a while it seemed nice despite having some odd ways of doing things that I think come from it originally being a C# and VB product. After playing with it for a while I decided to see if I could get JFreeChart charts to look the same way. As it turns out it wasn't that hard.
There isn't much difference between the charts but the one that stands out the most is that the ChartFX charts have a fancy border. This also happens to be something that JFreeChart can't do out of the box with all the other changes that need to be made are just settings that can be done in JFreeChart. So here is how I went about fixing it so that a JFreeChart has the fancy background.
The first thing you need is to be able to generate the chart as an image using JFreeChart.createBufferedImage. This will give you back a BufferedImage that you can then merge with the background you create.
The next thing you need is the background. In this case it is made with rounded edges, a gradient, and a drop shadow. The rounded edges and gradient are easy enough to make since they are just normal Java2D options (see the following code example for details). The real trick is the drop shadow. For that I looked around and found the following two articles: fast or good drop shadows and non-rectangular drop shadows. These weren't exactly what I needed because I already know the shape of the object every time but they gave me what I needed to create the shadow easily.
To generate the drop shadow I first draw the rounded edged rectangle with a gradient fill. Then I use the a convolve operation described in the above articles to add a nice fuzzy blur. The last thing I do is offset the blurred image a little and then overlay the original on top of it.
Here is all the code to create an example:
float data = new float[width * height];
float value = 1.0f / (float) (width * height);
for (int i = 0; i < data.length; i++)
data[i] = value;
return new ConvolveOp(new Kernel(width, height, data));
public static BufferedImage buildChartDropShadow(BufferedImage chartImage, int padding, Color backgroundColor)
BufferedImage shadow = new BufferedImage(chartImage.getWidth() + (padding*2), chartImage.getHeight() + (padding*2), BufferedImage.TYPE_INT_ARGB);
Graphics2D shadowCanvas = (Graphics2D) shadow.getGraphics();
shadowCanvas.fillRect(0, 0, chartImage.getWidth() + (padding*2), chartImage.getHeight() + (padding*2));
shadowCanvas.fillRoundRect(padding, padding, chartImage.getWidth(), chartImage.getHeight(), 20, 20);
BufferedImage finalImage = new BufferedImage(chartImage.getWidth() + (padding*2), chartImage.getHeight() + (padding*2), BufferedImage.TYPE_INT_ARGB);
Graphics2D finalCanvas = (Graphics2D) finalImage.getGraphics();
finalCanvas.setColor(backgroundColor == null ? Color.white : backgroundColor);
finalCanvas.fillRect(0, 0, chartImage.getWidth() + (padding*2), chartImage.getHeight() + (padding*2));
finalCanvas.drawImage(shadow, getLinearBlurOp(10, 10), 2, 2);
finalCanvas.setPaint(new GradientPaint(0.0f, 0.0f, new Color(0xdc, 0xe5, 0xf4), 0.0f, chartImage.getHeight() * 0.2f, new Color(0xff, 0xff, 0xff)));
finalCanvas.fillRoundRect(padding, padding, chartImage.getWidth(), chartImage.getHeight(), 20, 20);
finalCanvas.drawImage(chartImage, null, padding, padding);
JFreeChart jFreeChart = ChartFactory.createBarChart(null, null, "Test", dataset, PlotOrientation.VERTICAL, true, false, false);
jFreeChart.setPadding(new RectangleInsets(10, 5, 5, 5));
CategoryPlot plot = (CategoryPlot) jFreeChart.getPlot();
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setSeriesPaint(0, new Color(0x25, 0x64, 0xc1));
renderer.setSeriesPaint(1, new Color(0xc7, 0x38, 0x00));
renderer.setSeriesPaint(2, new Color(0x46, 0xb1, 0xc2));
renderer.setSeriesPaint(3, new Color(0x76, 0xc8, 0x2d));
NumberAxis numberaxis = (NumberAxis)plot.getRangeAxis();
DecimalFormat currencyFormat = (DecimalFormat) NumberFormat.getCurrencyInstance();
jFreeChart.getLegend().setBorder(0.0, 0.0, 0.0, 0.0);
int padding = 10;
int width = 500;
int height = 300;
ImageIO.write(GraphicsUtil.buildChartDropShadow(jFreeChart.createBufferedImage(width–(padding*2), height–(padding*2)), padding), "png", new FileOutputStream("/tmp/test.png"));
catch (IOException e)
throw new SystemException(e.getMessage(), e);
Here are the resulting graph differences. As you can see there aren't many and those that are still there could even be removed with a little more work.
ChartFX for Java: