Search code examples
javajfreechartlinechart

How to draw line chart using jfreechart from top to bottom?


I'm using jfreechart to draw line chart , I need the line to be drawn from top to bottom .... Meaning: 0,0 coordinates will be in the top-left corner. I was able to do it when I used 'CategoryPlot' just by change 'PlotOrientation' but label on the left became overlap..anyhow, I prefer 'xyplot'

changing 'setInverted' or 'setDomainAxisLocation' did not help

any help will be appreciated

update: I'm reposting my code for better clarity (chart drawing part )

In the first code: I got the needed output as showing here http://i58.tinypic.com/r1fr01.jpg just by passing 'PlotOrientation.HORIZONTAL' in this part, I'm using 'CategoryPlot'

import java.awt.*;

import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import org.jfree.ui.*;

public class PCategory extends ApplicationFrame
{
    public PCategory(String s)
    {
        super(s);
        JPanel jpanel = createDemoPanel();
        jpanel.setPreferredSize(new Dimension(300, 200));
        setContentPane(jpanel);
    }

    private static CategoryDataset createDataset()
    {

        DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();
        defaultcategorydataset.addValue(0,"Pixels", Integer.toString(0));
        defaultcategorydataset.addValue(2,"Pixels", Integer.toString(1));
        defaultcategorydataset.addValue(5,"Pixels", Integer.toString(2));
        defaultcategorydataset.addValue(10,"Pixels", Integer.toString(3));
        defaultcategorydataset.addValue(7,"Pixels", Integer.toString(4));
        defaultcategorydataset.addValue(8,"Pixels", Integer.toString(5));


        return defaultcategorydataset;
    }
    private static JFreeChart createChart(CategoryDataset categorydataset)
    {
        JFreeChart jfreechart = ChartFactory.createLineChart(null, null, null, categorydataset, PlotOrientation.HORIZONTAL, false, true, false);
        jfreechart.addSubtitle(new TextTitle("Title"));
        CategoryPlot categoryplot = (CategoryPlot)jfreechart.getPlot();
        categoryplot.setRangePannable(true);
        categoryplot.setRangeGridlinesVisible(false);

        ChartUtilities.applyCurrentTheme(jfreechart);
        LineAndShapeRenderer lineandshaperenderer = (LineAndShapeRenderer)categoryplot.getRenderer();
        lineandshaperenderer.setBaseShapesVisible(true);
        lineandshaperenderer.setDrawOutlines(true);
        lineandshaperenderer.setUseFillPaint(true);
        lineandshaperenderer.setBaseFillPaint(Color.white);
        lineandshaperenderer.setSeriesStroke(0, new BasicStroke(3F));
        lineandshaperenderer.setSeriesOutlineStroke(0, new BasicStroke(2.0F));
        lineandshaperenderer.setSeriesShape(0, new java.awt.geom.Ellipse2D.Double(-5D, -5D, 10D, 10D));

        return jfreechart;
    }

    public static JPanel createDemoPanel()
    {
        JFreeChart jfreechart = createChart(createDataset());
        ChartPanel chartpanel = new ChartPanel(jfreechart);
        chartpanel.setMouseWheelEnabled(true);

        return chartpanel;
    }

    public static void main(String args[])
    {
        PCategory PCategory = new PCategory("PCategory.java");
        PCategory.pack();
        RefineryUtilities.centerFrameOnScreen(PCategory);
        PCategory.setVisible(true);
    }
}

In the second code: I didn't get what I need even though I used same data and pass 'PlotOrientation.HORIZONTAL' as showing here http://i57.tinypic.com/11hq9tk.jpg I commented out my approach to solve the problem

import java.awt.Dimension;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.*;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

public class PXYPlot extends ApplicationFrame {
    public PXYPlot(String s) {
        super(s);
        JPanel jpanel = createPanel();
        jpanel.setPreferredSize(new Dimension(300, 200));
        setContentPane(jpanel);
    }
    private static XYDataset createDataset() {
        XYSeries xyseries = new XYSeries("Pixels", true);

        xyseries.add(0, 0);
        xyseries.add(2, 1);
        xyseries.add(5, 2);
        xyseries.add(10, 3);
        xyseries.add(7, 4);
        xyseries.add(8, 5);

        XYSeriesCollection xyseriescollection = new XYSeriesCollection();
        xyseriescollection.addSeries(xyseries);
        return xyseriescollection;

    }
    private static JFreeChart createChart(XYDataset xydataset)
    {
        JFreeChart Mychart = ChartFactory.createXYLineChart(null, null, null, xydataset, PlotOrientation.HORIZONTAL, true, true, false);
        XYPlot xyplot = (XYPlot) Mychart.getPlot();
        xyplot.setDomainPannable(true);
        xyplot.setRangePannable(true);
        XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyplot.getRenderer();
        xylineandshaperenderer.setBaseShapesVisible(true);
        xylineandshaperenderer.setBaseShapesFilled(true);


    /* ----------- this part is my attempt to solve the problem -----

        NumberAxis numberaxis = (NumberAxis)xyplot.getRangeAxis();
        numberaxis.setInverted(true);
        xyplot.setDomainAxisLocation(AxisLocation.TOP_OR_LEFT);

        //------------I like XYplot because of the part -----------------
        NumberAxis xAxis = new NumberAxis();
        xAxis.setTickUnit(new NumberTickUnit(1));
        XYPlot plot = (XYPlot) Mychart.getPlot();
        plot.setDomainAxis(xAxis);
        //-----------------------------
        numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        */

        return Mychart;
    }
    public static JPanel createPanel() {
        JFreeChart jfreechart = createChart(createDataset());
        ChartPanel chartpanel = new ChartPanel(jfreechart);
        chartpanel.setMouseWheelEnabled(true);
        return chartpanel;
    }
    public static void main(String args[]) {
        PXYPlot PXYPlot = new PXYPlot("PXYPlot.java");
        PXYPlot.pack();
        RefineryUtilities.centerFrameOnScreen(PXYPlot);
        PXYPlot.setVisible(true);
    }
}

I need 'XYPlot' because I have a huge amount of data , I think 'CategoryPlot' is not designed for it, beside I have overlapping issue with it. In addition, it needs number of overriding in order to meet my needs


Solution

  • First, create your dataset as follows then don't change it...the data is the same no matter how you want to present it:

        private XYDataset createDataset() {
            XYSeries s1 = new XYSeries("S1");
            s1.add(0, 0);
            s1.add(1, 2);
            s1.add(2, 5);
            s1.add(3, 10);
            s1.add(4, 7);
            s1.add(5, 8);
            XYSeriesCollection dataset = new XYSeriesCollection();
            dataset.addSeries(s1);
            return dataset;
       }
    

    Now a reasonably standard JFreeChart creation would look like this:

    enter image description here

    ...and here is the code:

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.geom.Ellipse2D;
    import javax.swing.JFrame;
    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.XYPlot;
    import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
    import org.jfree.data.xy.XYDataset;
    import org.jfree.data.xy.XYSeries;
    import org.jfree.data.xy.XYSeriesCollection;
    
    public class StackOverflow25993430 extends JFrame {
    
        public StackOverflow25993430(String title) {
            super(title);
            JFreeChart chart = createChart(createDataset());
            ChartPanel panel = new ChartPanel(chart);
            panel.setPreferredSize(new Dimension(500, 300));
            setContentPane(panel);
        }
    
        private XYDataset createDataset() {
            XYSeries s1 = new XYSeries("S1");
            s1.add(0, 0);
            s1.add(1, 2);
            s1.add(2, 5);
            s1.add(3, 10);
            s1.add(4, 7);
            s1.add(5, 8);
            XYSeriesCollection dataset = new XYSeriesCollection();
            dataset.addSeries(s1);
            return dataset;
        }
    
        private JFreeChart createChart(XYDataset dataset) {
            JFreeChart chart = ChartFactory.createXYLineChart(
                    "StackOverflow25993430", "X", "Y", dataset);
            chart.removeLegend();
            XYPlot plot = (XYPlot) chart.getPlot();
            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
            renderer.setSeriesShapesVisible(0, true);
            renderer.setSeriesShape(0, new Ellipse2D.Double(-4.0, -4.0, 8.0, 8.0));
            renderer.setSeriesFillPaint(0, Color.WHITE);
            renderer.setUseFillPaint(true);
            NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
            xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
            return chart;
        }
    
        public static void main(String[] args) {
            JFrame app = new StackOverflow25993430("JFreeChart");
            app.pack();
            app.setVisible(true);
        }
    }
    

    Very little needs changing to get the plot you want. First, the plot orientation should be changed, second the x-axis should be inverted, and third you have to provide a hint that the y-axis should go at the top. Here is the result:

    enter image description here

    ... and the code to produce it (with *** marking the 5 lines that were added):

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.geom.Ellipse2D;
    import javax.swing.JFrame;
    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.ChartPanel;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.axis.AxisLocation; // ***
    import org.jfree.chart.axis.NumberAxis;
    import org.jfree.chart.plot.PlotOrientation; // ***
    import org.jfree.chart.plot.XYPlot;
    import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
    import org.jfree.data.xy.XYDataset;
    import org.jfree.data.xy.XYSeries;
    import org.jfree.data.xy.XYSeriesCollection;
    
    public class StackOverflow25993430b extends JFrame {
    
        public StackOverflow25993430b(String title) {
            super(title);
            JFreeChart chart = createChart(createDataset());
            ChartPanel panel = new ChartPanel(chart);
            panel.setPreferredSize(new Dimension(500, 300));
            setContentPane(panel);
        }
    
        private XYDataset createDataset() {
            XYSeries s1 = new XYSeries("S1");
            s1.add(0, 0);
            s1.add(1, 2);
            s1.add(2, 5);
            s1.add(3, 10);
            s1.add(4, 7);
            s1.add(5, 8);
            XYSeriesCollection dataset = new XYSeriesCollection();
            dataset.addSeries(s1);
            return dataset;
        }
    
        private JFreeChart createChart(XYDataset dataset) {
            JFreeChart chart = ChartFactory.createXYLineChart(
                    "StackOverflow25993430b", "X", "Y", dataset);
            chart.removeLegend();
            XYPlot plot = (XYPlot) chart.getPlot();
            plot.setOrientation(PlotOrientation.HORIZONTAL); // ***
            plot.setRangeAxisLocation(AxisLocation.TOP_OR_LEFT); // ***
            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();
            renderer.setSeriesShapesVisible(0, true);
            renderer.setSeriesShape(0, new Ellipse2D.Double(-4.0, -4.0, 8.0, 8.0));
            renderer.setSeriesFillPaint(0, Color.WHITE);
            renderer.setUseFillPaint(true);
            NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();
            xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
            xAxis.setInverted(true); // ***
            return chart;
        }
    
        public static void main(String[] args) {
            JFrame app = new StackOverflow25993430b("JFreeChart");
            app.pack();
            app.setVisible(true);
        }
    }