Simple Pie Chart in Java Swing

Update !

This pie chart compoment has now been moved into the Iceberg Charts project . Please use Iceberg Charts for a more complete charting experience.

I know there are a lot of Swing charting software libraries out there (JFreechart comes to mind). But a lot of them come across as too bloated and require a lot of time to become familiar with.

My own Piechart is as simple as it gets; collect your segments as percentages in a list, along with the corresponding colours :

You can get something that looks like this :

Its really basic, but its also very minimalist and does away with a lot of noise that other charting programs offer.

Simple Indicator.

I thought I would also add a couple more modes to my pie chart. The second mode is what I would call a simple indicator mode. This displays just one percentage value as a slice of the pie.

I find these indicators look very effective as small graphics next to numerical text, as the following example tries to show:

I’m not 100% sure this is the best way to visually enhance percentages, but I think it looks good in certain situations.

Graded Indicator.

Another visual approach to showing a percentage growing into a critical phase, is to somehow grade the colors as the percentage level gets higher. I decided to create a third mode which allows the user to set a number of gradings with corresponding colors. As the percentage gets close to 100% the pie sections get smaller and the colors get more prominent.

Here is an example :

To use the third mode simply add an array of percentages with an array of colours, plus an overall percentage, to a third constructor :

Here is the source code to the pie chart with all three modes :

 


Posted in Swing | Tagged , , , | 11 Comments

11 Responses to Simple Pie Chart in Java Swing

  1. Ruwan Rathnayake says:

    Wow! Gotta say after searching and studying many Charting libraries, this is the easiest and the simplest one I’ve found. It’s so simple as even a newbie can use it really easily. And you have explained how to use it in a really clear way. Keep up the great work felixzacat!

  2. zlloyd1 says:

    I cannot get this code to work, because I keep getting errors about the lines,
    g2d.setColor(colors.get(i));
    Double val = values.get(i);
    saying, incompatible types,
    required: color
    found: object
    Am I missing something here??

    • felixzacat says:

      you should be passing in an array of Double values, and an array of Color objects. Maybe you are passing in the wrong object type?

      • Tiwaking says:

        Third time lucky. I’ve been trying to type in ArrayList*Double* (replace * with greater than/less than) and the code is automatically parsed and removed the greater than/less than signs. I think that is what has happened to the generics in your code example. There must be a greater-than/less-than escape character some where.
        Thanks for the pie chart!!

    • Tiwaking says:

      felixzacat is missing the Generic Type for the ArrayList

      // private ArrayList values;//felixzacat didnt generic this
      private ArrayListvalues;
      // private ArrayList colors;//felixzacat didnt generic this
      private ArrayListcolors;
      // private ArrayList gradingValues;//felixzacat didnt generic this
      private ArrayListgradingValues;
      // private ArrayList gradingColors;//felixzacat didnt generic this
      private ArrayListgradingColors;

      And here

      public PieChart(ArrayListvalues, ArrayListcolors) {

      And here

      public PieChart(int percent, ArrayListgradingValues, ArrayListgradingColors) {

  3. Philipp says:

    Nice job dude,
    saves me a lot of time.

    Just as a hint: You can use generics for the different ArrayList, like ArrayList.
    I get compile errors with the code above if i dont use generics or cast to the right Type.

    But really, thx a lot.

    • Tiwaking says:

      This is really strange: I typed in ArrayList and ArrayList with the code tags and it automatically removes and
      I think it has something to do with the code tags

  4. Simon Williams says:

    I used this and it’s pretty simple, I did have a slight problem where it wasn’t displaying. This display problem was due to my lack of Java knowledge where I did not set the size of the piechart.

    If you’re just fiddling don’t forget to do something like this to see it appear:
    pieChart.setSize(100, 100);

  5. Dave Smith says:

    Thanks for the code! I ported it over to SWT, here’s the SWT version (the main function is just there for testing)

    package com.gg.piechart;
    import java.util.ArrayList;

    import org.eclipse.swt.SWT;
    import org.eclipse.swt.events.PaintEvent;
    import org.eclipse.swt.events.PaintListener;
    import org.eclipse.swt.graphics.Color;
    import org.eclipse.swt.graphics.GC;
    import org.eclipse.swt.graphics.Point;
    import org.eclipse.swt.layout.FillLayout;
    import org.eclipse.swt.widgets.Canvas;
    import org.eclipse.swt.widgets.Composite;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Shell;

    public class PieChart extends Canvas
    {

    public PieChart(Composite parent, int style)
    {
    super(parent, style);
    type = Type.SIMPLE_INDICATOR;
    this.percent = 15.0;
    addPaintListener(new PaintListener()
    {
    public void paintControl(PaintEvent e) {
    paint(e);
    }
    });
    }

    enum Type {
    STANDARD, SIMPLE_INDICATOR, GRADED_INDICATOR
    }

    private Type type = null; //the type of pie chart

    private ArrayList values;
    private ArrayList colors;

    private ArrayList gradingValues;
    private ArrayList gradingColors;

    double percent = 0; //percent is used for simple indicator and graded indicator

    public void setPercent(int percent)
    {
    type = Type.SIMPLE_INDICATOR;
    this.percent = percent;
    }

    public void setValues(ArrayList values, ArrayList colors)
    {
    type = Type.STANDARD;

    this.values = values;
    this.colors = colors;
    }

    public void setPercentAndGrading(int percent, ArrayList gradingValues, ArrayList gradingColors)
    {
    type = Type.GRADED_INDICATOR;
    this.gradingValues = gradingValues;
    this.gradingColors = gradingColors;
    this.percent = percent;

    }

    protected void paint(PaintEvent pe)
    {
    Point size = getSize();
    int diameter = size.x > size.y ? size.y:size.x;

    GC gc = pe.gc;
    Display display = pe.display;
    gc.setAntialias(SWT.ON);

    if (type == Type.SIMPLE_INDICATOR)
    {
    //colors used for simple indicator
    Color backgroundColor = display.getSystemColor(SWT.COLOR_WHITE);//SWTResourceManager.getColor(SWT.COLOR_WHITE);
    Color mainColor = display.getSystemColor(SWT.COLOR_BLUE);//SWTResourceManager.getColor(SWT.COLOR_BLUE);
    gc.setBackground(backgroundColor);
    gc.fillOval(0, 0, diameter, diameter);
    gc.setBackground(mainColor);
    Double angle = (percent / 100) * 360;
    gc.fillArc(0, 0, diameter, diameter, -270, -angle.intValue());

    }
    else if (type == Type.STANDARD)
    {
    int lastPoint = -270;

    for (int i = 0; i < values.size(); i++)
    {
    gc.setForeground(colors.get(i));

    Double val = values.get(i);
    Double angle = (val / 100) * 360;

    gc.fillArc(0, 0, diameter, diameter, lastPoint, -angle.intValue());
    System.out.println("fill arc " + lastPoint + " "
    + -angle.intValue());

    lastPoint = lastPoint + -angle.intValue();
    }
    }
    else if (type == Type.GRADED_INDICATOR)
    {

    int lastPoint = -270;

    double gradingAccum = 0;

    for (int i = 0; i percent)
    {

    System.out.println(“gradingAccum > percent”);

    //get the previous accumulated segments. Segments minus last one
    double gradingAccumMinusOneSegment = gradingAccum – val;

    //make an adjusted calculation of the last wedge
    angle = ((percent – gradingAccumMinusOneSegment) / 100) * 360;

    gc.fillArc(0, 0, diameter, diameter, lastPoint, -angle.intValue());

    lastPoint = lastPoint + -angle.intValue();

    break;
    }
    else
    {

    System.out.println(“normal”);
    angle = (val / 100) * 360;

    gc.fillArc(0, 0, diameter, diameter, lastPoint, -angle.intValue());

    System.out.println(“fill arc ” + lastPoint + ” ”
    + -angle.intValue());

    lastPoint = lastPoint + -angle.intValue();
    }
    }
    }
    }

    public static void main(String[] args)
    {
    Display display = new Display();
    final Shell shell = new Shell(display, SWT.SHELL_TRIM);
    shell.setLayout(new FillLayout());
    PieChart chart = new PieChart(shell, SWT.NONE);
    chart.setPercent(25);
    shell.setSize(500, 500);
    shell.open();
    while (!shell.isDisposed()) {
    if (!display.readAndDispatch())
    display.sleep();
    }
    display.dispose();
    }
    }

  6. Keks says:

    Hey, thank you for your code.
    I was wondering if it is possible to use the piecharts in a loop. I tried it with an array of piecharts and it worked nearly right – they had all the same value at the end which is not right but while I debugged it every value was right. I hope you know what I mean and maybe you have an idea what I’m doing wrong?! Thank you in advance!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

THREE_COLUMN_PAGE