Changing the colors of a bar chart in JFreeChart – Does it really have to be this much work?

9

The default colors of the first two bars in a bar chart are red and blue. We created a chart for a customer, but he wanted red and green bars. Changing that color takes about five minutes, I thought. But when I tried it, it took me way more time.

First of all I think that JFreeChart should rename itself to JNotSoFreeChart, when I look for documentation I only see this : "> Click here to BUY the JFreeChart Developer Guide <". Of course it’s great that we can use JFreeChart for free, but at least provide a little bit of documentation and write a book that people can buy in a store. AMIS wil definitely buy that book.

....

I hooked up the debugger to our chart drawing class and found out that the colors come from an object that implements the DrawingSupplier interface. I can’t find a way to create such an object, so I had to create one myself.
As we can see in the javadoc of DrawingSupplier we have to implement 5 methods. For a simple bar chart the outline, outline stroke, shape and stroke will always be the same, so we can use static fields for these objects.

My implementation of DrawingSupplier:

<code><br /><font color="#7f0055"><strong>public&nbsp;class&nbsp;</strong></font><font color="#000000">AmisDrawingSupplier&nbsp;</font><font color="#7f0055"><strong>implements&nbsp;</strong></font><font color="#000000">DrawingSupplier&nbsp;</font><font color="#000000">{</font><br /><br /><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><strong>private&nbsp;static&nbsp;</strong></font><font color="#000000">Stroke&nbsp;stroke&nbsp;=&nbsp;</font><font color="#7f0055"><strong>new&nbsp;</strong></font><font color="#000000">BasicStroke</font><font color="#000000">()</font><font color="#000000">;</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>private&nbsp;static&nbsp;</strong></font><font color="#000000">Shape&nbsp;shape&nbsp;=&nbsp;</font><font color="#7f0055"><strong>new&nbsp;</strong></font><font color="#000000">Rectangle2D.Double</font><font color="#000000">()</font><font color="#000000">;</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>private&nbsp;</strong></font><font color="#7f0055"><strong>int&nbsp;</strong></font><font color="#000000">cursor&nbsp;=&nbsp;</font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>private&nbsp;</strong></font><font color="#000000">List&lt;Color&gt;&nbsp;colorList;</font><br /><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>public&nbsp;</strong></font><font color="#000000">LocatusDrawingSupplier</font><font color="#000000">(</font><font color="#000000">List&lt;Color&gt;&nbsp;colorList</font><font color="#000000">)&nbsp;{</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>this</strong></font><font color="#000000">.colorList&nbsp;=&nbsp;colorList;</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#000000">}</font><br /><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>public&nbsp;</strong></font><font color="#000000">Paint&nbsp;getNextPaint</font><font color="#000000">()&nbsp;{</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>if&nbsp;</strong></font><font color="#000000">(</font><font color="#000000">colorList&nbsp;==&nbsp;</font><font color="#7f0055"><strong>null&nbsp;</strong></font><font color="#000000">||&nbsp;colorList.size</font><font color="#000000">()&nbsp;</font><font color="#000000">==&nbsp;</font><font color="#990000">0</font><font color="#000000">)&nbsp;{</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>return&nbsp;</strong></font><font color="#000000">Color.RED;&nbsp;</font><font color="#3f7f5f">//return&nbsp;red&nbsp;on&nbsp;empty&nbsp;or&nbsp;no&nbsp;list</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#000000">}</font><br /><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#000000">Color&nbsp;returnColor=colorList.get</font><font color="#000000">(</font><font color="#000000">cursor</font><font color="#000000">)</font><font color="#000000">;</font><br /><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">cursor++;</font><br /><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#3f7f5f">//wrap&nbsp;cursor&nbsp;when&nbsp;all&nbsp;items&nbsp;in&nbsp;the&nbsp;list&nbsp;are&nbsp;traversed</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>if&nbsp;</strong></font><font color="#000000">(</font><font color="#000000">cursor&nbsp;&gt;=&nbsp;colorList.size</font><font color="#000000">())&nbsp;{</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#000000">cursor&nbsp;=&nbsp;</font><font color="#990000">0</font><font color="#000000">;</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#000000">}</font><br /><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>return&nbsp;</strong></font><font color="#000000">returnColor;</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#000000">}</font><br /><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>public&nbsp;</strong></font><font color="#000000">Paint&nbsp;getNextOutlinePaint</font><font color="#000000">()&nbsp;{&nbsp;</font><font color="#7f0055"><strong>return&nbsp;</strong></font><font color="#000000">Color.BLACK;&nbsp;</font><font color="#000000">}</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>public&nbsp;</strong></font><font color="#000000">Stroke&nbsp;getNextStroke</font><font color="#000000">()&nbsp;{&nbsp;</font><font color="#7f0055"><strong>return&nbsp;</strong></font><font color="#000000">stroke;&nbsp;</font><font color="#000000">}</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>public&nbsp;</strong></font><font color="#000000">Stroke&nbsp;getNextOutlineStroke</font><font color="#000000">()&nbsp;{&nbsp;</font><font color="#7f0055"><strong>return&nbsp;</strong></font><font color="#000000">stroke;&nbsp;</font><font color="#000000">}</font><br /><font color="#ffffff">&nbsp;&nbsp;&nbsp; </font><font color="#7f0055"><strong>public&nbsp;</strong></font><font color="#000000">Shape&nbsp;getNextShape</font><font color="#000000">()&nbsp;{&nbsp;</font><font color="#7f0055"><strong>return&nbsp;</strong></font><font color="#000000">shape;&nbsp;</font><font color="#000000">}</font><br /><font color="#000000">}</font></code>

I decided to give my DrawingSupplier a list with colors, when you prefer an array or random colors that’s also fine.

The final step is hooking up the DrawingSupplier to your chart:

<code><br /><font color="#000000">JFreeChart&nbsp;chart&nbsp;=&nbsp;...&nbsp;create&nbsp;chart&nbsp;here&nbsp;...</font><br /><font color="#000000">List&lt;Color&gt;&nbsp;colorList&nbsp;=&nbsp;..&nbsp;create&nbsp;list&nbsp;with&nbsp;colors&nbsp;here&nbsp;...</font><br /><font color="#000000">CategoryPlot&nbsp;cp&nbsp;=&nbsp;chart.getCategoryPlot</font><font color="#000000">()</font><font color="#000000">;</font><br /><font color="#000000">DrawingSupplier&nbsp;ds&nbsp;=&nbsp;</font><font color="#7f0055"><strong>new&nbsp;</strong></font><font color="#000000">AmisDrawing
Supplier</font><font color="
#000000">(</font><font color="#000000">colorList</font><font color="#000000">)</font><font color="#000000">;</font><br /><font color="#000000">cp.setDrawingSupplier</font><font color="#000000">(</font><font color="#000000">ds</font><font color="#000000">)</font><font color="#000000">;</font></code>

And here the final result:

Conclusion

Well, that wasn’t to difficult wasn’t it?, it’s only too much work for such a simple thing.
Maybe I overlooked something, but I’m afraid this is the easiest way to change the color of a bar.

Share.

About Author

9 Comments

  1. Try this (apologies if the formatting is bad):

    CategoryPlot plot = (CategoryPlot) chart.getPlot();
    BarRenderer renderer = (BarRenderer) plot.getRenderer();
    renderer.setSeriesPaint(0, Color.red);
    renderer.setSeriesPaint(1, Color.green);

  2. Marc, when using commons-io you can do the following:
    File file = new File(“/commons/io/project.properties”);
    List lines = FileUtils.readLines(file, “UTF-8″);
    It also has stuff like line iterators resembling the way Ruby lets you access files. How much easier should it be?

  3. Jeroen van Wilgenburg on

    I think I didn’t look at the Javadoc at that time. Clicking on implement methods in my IDE has become to easy I guess ;-)

    The static fields are what I meant with default sequences.

    This makes this blog a bit useless, but at least someone else will find out how to do it when searching on google ;-)

    Mark >> With most open source libraries things actually become easier, there probably is an open source library that does IO for you the easy way. But I understand what you mean, things with Dates are also way too strange in Java.

  4. As you can see the DefaultDrawingSupplier has a couple of static fields containing the default sequences (like DEFAULT_OUTLINE_STROKE_SEQUENCE) which you can use to construct the new object. Strange that you didn’t see it though; it’s the only implementing class of the DrawingSupplier interface.

  5. Jeroen van Wilgenburg on

    I didn’t find the DefaultDrawingSupplier when I was figuring out how to do it. But it should do the trick, only drawback is that you have to put all the default sequences in the constructor when you only want a different paint sequence. But it is still way shorter than my idea. Thanks!

  6. Mark Hatham on

    But isn’t that the mantra of the Java World? Make things hard for things that should be much simpler.

    How to read a file?