Search code examples
javaxmljfreechart

simple jfreechart bar chart using xml file


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


Solution

  • 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