1

I need to generate a bar graph (shown below) based on the value of "state" field in the XML file. The bars on the Y axis are the "key" field in the XML file. (Plan-A, Plan-B, etc.).

The color of these bars are dependent on the "state" field in the corresponding tags. (Success - Green, Failed - Red, InProgress - Blue)

I tried googling how to generate the bar graph by reading an XML file. But i couldn't figure it out.

Please help me out in figuring out parsing the "state" field from the xml file & the correct jfreechart for this use case.

xml file content:

<results>
<result id="1" number="10" lifeCycleState="Finished" state="Failed" key="PLAN-A">
</result>

<result id="2" number="20" lifeCycleState="Finished" state="Success" key="PLAN-B">
</result>

<result id="3" number="30" lifeCycleState="Finished" state="Success" key="PLAN-C">
</result>

<result id="4" number="40" lifeCycleState="InProgress" state="InProgress" key="PLAN-D">
</result>
</results>

Chart is :

enter image description here

SS Hegde
  • 729
  • 2
  • 14
  • 33

2 Answers2

2

Here's an example of what you are looking for:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class BarChartDemo extends ApplicationFrame {


    public BarChartDemo(final String title) throws Exception {

        super(title);

        final CategoryDataset dataset = createDataset();
        final JFreeChart chart = createChart(dataset);
        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new Dimension(500, 270));
        setContentPane(chartPanel);

    }

    /**
     * Returns a sample dataset.
     * 
     * @return The dataset.
     * @throws ParserConfigurationException 
     * @throws IOException 
     * @throws SAXException 
     */
    private CategoryDataset createDataset() throws Exception {
        final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         Document document = db.parse(new File("src/input.xml"));
         NodeList nodeList = document.getElementsByTagName("result");


         for(int x=nodeList.getLength()-1;x>=0;x--){
             dataset.addValue(10.0, nodeList.item(x).getAttributes().getNamedItem("state").getNodeValue(),nodeList.item(x).getAttributes().getNamedItem("key").getNodeValue());
         }

        return dataset;

    }

    /**
     * Creates a sample chart.
     * 
     * @param dataset  the dataset.
     * 
     * @return The chart.
     */
    private JFreeChart createChart(final CategoryDataset dataset) {

        // create the chart...
        final JFreeChart chart = ChartFactory.createBarChart(
            "Bar Chart Demo",         // chart title
            "key",               // domain axis label
            "number",                  // range axis label
            dataset,                  // data
            PlotOrientation.HORIZONTAL, // orientation
            true,                     // include legend
            true,                     // tooltips?
            false                     // URLs?
        );

        // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...

        // set the background color for the chart...
        chart.setBackgroundPaint(Color.white);

        // get a reference to the plot for further customisation...
        final CategoryPlot plot = chart.getCategoryPlot();
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);

        // set the range axis to display integers only...
        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        // disable bar outlines...
        final BarRenderer renderer = (BarRenderer) plot.getRenderer();
        renderer.setDrawBarOutline(false);

        // set up gradient paints for series...
        final GradientPaint gp0 = new GradientPaint(
            0.0f, 0.0f, Color.blue, 
            0.0f, 0.0f, Color.lightGray
        );
        final GradientPaint gp1 = new GradientPaint(
            0.0f, 0.0f, Color.green, 
            0.0f, 0.0f, Color.lightGray
        );
        final GradientPaint gp2 = new GradientPaint(
            0.0f, 0.0f, Color.red, 
            0.0f, 0.0f, Color.lightGray
        );
        renderer.setSeriesPaint(0, gp0);
        renderer.setSeriesPaint(1, gp1);
        renderer.setSeriesPaint(2, gp2);

   final CategoryAxis domainAxis = plot.getDomainAxis();
    domainAxis.setCategoryLabelPositions(
        CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0)
    );

        return chart;

    }


    public static void main(final String[] args) throws Exception {

        final BarChartDemo demo = new BarChartDemo("Barchart");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

    }

}

Edit: to fix colors based on the status value, do following:

 /*   renderer.setSeriesPaint(0, gp0);
    renderer.setSeriesPaint(1, gp1);
    renderer.setSeriesPaint(2, gp2);*/

comment the above piece of code in your program , and add below code instead:

int pos=0;
   List<Comparable> statusList = dataset.getRowKeys();
   for(Comparable status : statusList){

       if(status.equals("InProgress")){
           renderer.setSeriesPaint(pos,gp0);
       }
       else if (status.equals("Success")){
           renderer.setSeriesPaint(pos,gp1);
       }
       else if (status.equals("Failed")){
           renderer.setSeriesPaint(pos,gp2);
       }
       pos++;
   }

Edit2: to save as image, in createChart method , just before doing return chart, add your code:

        int width=640; 
        int height=480; 
        File BarChart=new File("src/chart.png"); 
        ChartUtilities.saveChartAsPNG(BarChart, chart, width, height);
        return chart;

When you run the program it will give you following: enter image description here

user3487063
  • 3,672
  • 1
  • 17
  • 24
  • But these color representations gets changed in the graph if xml file order changes. Suppose if the PLAN-A's "state" in the xml file is "Success" then in the graph the color would become "Blue" for success. How can i make the color in the graph as static ? (Failed - Red, Success - Green, InProgress - Blue) – SS Hegde Sep 04 '14 at 08:23
  • 1
    See my edit to have colors based on the status, but still without making the edits , if you change status of PLAN-A's status to "Success", the graph would show "Green" bar only. – user3487063 Sep 04 '14 at 13:45
  • Thats like a spoon feed :P Thanks a lot. I tried to save the graph as image using the following code. But i am unable to. Can you have a look. I have added these codes after commenting `demo.setVisible(true);`. And then i added: `File BarChart=new File("chart.png"); ChartUtilities.saveChartAsPNG(BarChart,demo,width,height);` – SS Hegde Sep 04 '14 at 14:15
  • 1
    move that piece of code to createChart method , just save as image just before returning, should be: ChartUtilities.saveChartAsPNG(BarChart, chart, width, height); – user3487063 Sep 04 '14 at 14:37
  • Can you please have a look at http://stackoverflow.com/questions/25745781/jfreechart-setting-the-date-ticks-in-x-axis-from-the-current-date – SS Hegde Sep 09 '14 at 13:58
  • It will be of great help if you can have a look here. (http://stackoverflow.com/questions/25751516/jfreechar-stackedbarchart-customization) – SS Hegde Sep 09 '14 at 18:39
  • Sure @SSHegde, I'll have a look at both your questions in sometime . Thank you :) – user3487063 Sep 09 '14 at 18:48
  • I tried modifying the same program for stacked bar chart. But i am stuck how to process those time & then adjust them in graph. – SS Hegde Sep 10 '14 at 03:36
  • Sorry @SSHegde , I didn't get enough time to look in to your question yesterday . I'll be doing that now:). – user3487063 Sep 10 '14 at 13:05
  • Thats of great help user3487063. (I am c++ programmer ,that too on linux. This field is very much new to me. I am sorry if i have pushed too much towards you) – SS Hegde Sep 10 '14 at 14:32
  • no problem, I'll definitely look into it as I get some time. Mostly, I'd try to answer that by the end of the day. – user3487063 Sep 10 '14 at 14:33
  • Seems you havent got time yesterday, please do have a look today on http://stackoverflow.com/questions/25751516/jfreechart-stackedbarchart-customization – SS Hegde Sep 11 '14 at 03:09
  • Please do have a look. – SS Hegde Sep 12 '14 at 05:56
  • @SSHegde, I took some time yesterday to solve that, but looks like a complicated one. Actually, I never worked with jfreechart before.I'll give it a shot as I get some time in between my work. – user3487063 Sep 12 '14 at 13:46
  • thats of great help from you. – SS Hegde Sep 13 '14 at 05:51
  • i even tried to code it. But i am unable to match according to the date. In fact i am unable to generate a graph with the dates starting from past seven days and end at the currant day. seems i am stranded :P – SS Hegde Sep 14 '14 at 16:34
1

one small point, the graph is showing 10.0 for all values. change: dataset.addValue(10.0, ... to: dataset.addValue( Double.valueOf(nodeList.item(x).getAttributes().getNamedItem("number").getNodeValue()), ...

brl
  • 11
  • 2