Link to home
Start Free TrialLog in
Avatar of dshrenik
dshrenikFlag for United States of America

asked on

JFreeChart: Time Series Chart

In my TimeSeries chart, I want to display text just above or next to a data point.

If possible, please provide some sample code. Thanks!
Avatar of for_yan
for_yan
Flag of United States of America image

there is ItemLabelGeneartor - check here:

http://stackoverflow.com/questions/3146823/is-it-possible-to-add-legend-to-the-plot-in-jfreechart

and in the chapter 12 of the manual.
It can be done on the BarChart, but
I'm not sure it can be done within the LineChart - I don't think I saw any picture of it

Avatar of dshrenik

ASKER

This example shows how it can be done. But, I want specific labels for each data point. Please let me know how I can do that. Thanks!

https://sites.google.com/site/drjohnbmatthews/jfreechartdemo
Look, how I modified it:

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
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.axis.TickUnitSource;
import org.jfree.chart.labels.StandardXYItemLabelGenerator;
import org.jfree.chart.labels.XYItemLabelGenerator;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RefineryUtilities;

/**
 * @author John B. Matthews
 */
public class JFreeChartDemo extends JFrame {

    private static final int MAX = 8;
    private static final Random random = new Random();

    /**
     * Construct a new frame
     *
     * @param title the frame title
     */
    public JFreeChartDemo(String title) {
        super(title);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final DefaultXYDataset dataset = new DefaultXYDataset();
        dataset.addSeries("Series0", createSeries(0));
        dataset.addSeries("Series1", createSeries(1));
        JFreeChart chart = createChart(dataset);
        ChartPanel chartPanel = new ChartPanel(chart, false);
        chartPanel.setPreferredSize(new Dimension(640, 480));
        this.add(chartPanel, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel();
        JButton addButton = new JButton("Add Series");
        buttonPanel.add(addButton);
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int n = dataset.getSeriesCount();
                dataset.addSeries("Series" + n, createSeries(n));
            }
        });
        JButton remButton = new JButton("Remove Series");
        buttonPanel.add(remButton);
        remButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int n = dataset.getSeriesCount() - 1;
                dataset.removeSeries("Series" + n);
            }
        });
        this.add(buttonPanel, BorderLayout.SOUTH);
    }

    /**
     * Create a series
     *
     * @ return the series
     */
    private double[][] createSeries(int mean) {
        double[][] series = new double[2][MAX];
        for (int i = 0; i < MAX; i++) {
            series[0][i] = (double) i;
            series[1][i] = mean + random.nextGaussian() / 2;

        }
        return series;
    }

    /**
     * Create a chart.
     *
     * @param dataset the dataset
     * @return the chart
     */
    private JFreeChart createChart(XYDataset dataset) {

        // create the chart...
        JFreeChart chart = ChartFactory.createXYLineChart(
            "Serial Data", // chart title
            "Domain", // domain axis label
            "Range", // range axis label
            dataset,  // initial series
            PlotOrientation.VERTICAL, // orientation
            true, // include legend
            true, // tooltips?
            false // URLs?
            );

        // set chart background
        chart.setBackgroundPaint(Color.white);

        // set a few custom plot features
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setBackgroundPaint(new Color(0xffffe0));
        plot.setDomainGridlinesVisible(true);
        plot.setDomainGridlinePaint(Color.lightGray);
        plot.setRangeGridlinePaint(Color.lightGray);

        // set the plot's axes to display integers
        TickUnitSource ticks = NumberAxis.createIntegerTickUnits();
        NumberAxis domain = (NumberAxis) plot.getDomainAxis();
        domain.setStandardTickUnits(ticks);
        NumberAxis range = (NumberAxis) plot.getRangeAxis();
        range.setStandardTickUnits(ticks);

        // render shapes and lines
        XYLineAndShapeRenderer renderer =
            new XYLineAndShapeRenderer(true, true);
        plot.setRenderer(renderer);
        renderer.setBaseShapesVisible(true);
        renderer.setBaseShapesFilled(true);

        // set the renderer's stroke
        Stroke stroke = new BasicStroke(
            3f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
        renderer.setBaseOutlineStroke(stroke);

        // label the points
        NumberFormat format = NumberFormat.getNumberInstance();
        format.setMaximumFractionDigits(2);
              /*
        XYItemLabelGenerator generator =
            new StandardXYItemLabelGenerator(
                StandardXYItemLabelGenerator.DEFAULT_ITEM_LABEL_FORMAT,
                format, format);
        */
               XYItemLabelGenerator generator = new  MyItemLabelGenerator();

        renderer.setBaseItemLabelGenerator(generator);
        renderer.setBaseItemLabelsVisible(true);

        return chart;
    }

    /** Main method */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFreeChartDemo demo = new JFreeChartDemo("JFreeChartDemo");
                demo.pack();
                demo.setLocationRelativeTo(null);
                demo.setVisible(true);
            }
         });
    }
}
class MyItemLabelGenerator extends StandardXYItemLabelGenerator {

public String generateLabel (XYDataset dataset, int series, int item){
    if(series == 0 && item == 2)return "good dog";
    else  if(series == 1 && item == 3)return "bad cat";
    else return "("+ series + "," + item + ")";


}


}

Open in new window

Thanks for the code.
But, I requirement is a little different. I extract the data points from an ArrayList of objects of a class Dummy. Dummy has 2 fields:
1. value -> data point on the graph
2. description -> description of the data point

I want to display the description in the label.

Thanks!



 
ASKER CERTIFIED SOLUTION
Avatar of for_yan
for_yan
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Awesome. Thanks!
You are always welcome.

On this particular chart it truncates the text to the left of the
first point, so you can add some spaces to the first label like in the code below.

Maybe it will not be an issue fior your chart - if you have
different location of origin and axes relative to the boundaries of the chart

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
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.axis.TickUnitSource;
import org.jfree.chart.labels.StandardXYItemLabelGenerator;
import org.jfree.chart.labels.XYItemLabelGenerator;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RefineryUtilities;

/**
 * @author John B. Matthews
 */
public class JFreeChartDemo extends JFrame {

    private static final int MAX = 8;
    private static final Random random = new Random();

    /**
     * Construct a new frame
     *
     * @param title the frame title
     */
    public JFreeChartDemo(String title) {
        super(title);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final DefaultXYDataset dataset = new DefaultXYDataset();
        dataset.addSeries("Series0", createSeries(0));
        dataset.addSeries("Series1", createSeries(1));
        JFreeChart chart = createChart(dataset);
        ChartPanel chartPanel = new ChartPanel(chart, false);
        chartPanel.setPreferredSize(new Dimension(640, 480));
        this.add(chartPanel, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel();
        JButton addButton = new JButton("Add Series");
        buttonPanel.add(addButton);
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int n = dataset.getSeriesCount();
                dataset.addSeries("Series" + n, createSeries(n));
            }
        });
        JButton remButton = new JButton("Remove Series");
        buttonPanel.add(remButton);
        remButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int n = dataset.getSeriesCount() - 1;
                dataset.removeSeries("Series" + n);
            }
        });
        this.add(buttonPanel, BorderLayout.SOUTH);
    }

    /**
     * Create a series
     *
     * @ return the series
     */
    private double[][] createSeries(int mean) {
        double[][] series = new double[2][MAX];
        for (int i = 0; i < MAX; i++) {
            series[0][i] = (double) i;
            series[1][i] = mean + random.nextGaussian() / 2;

        }
        return series;
    }

    /**
     * Create a chart.
     *
     * @param dataset the dataset
     * @return the chart
     */
    private JFreeChart createChart(XYDataset dataset) {

        // create the chart...
        JFreeChart chart = ChartFactory.createXYLineChart(
            "Serial Data", // chart title
            "Domain", // domain axis label
            "Range", // range axis label
            dataset,  // initial series
            PlotOrientation.VERTICAL, // orientation
            true, // include legend
            true, // tooltips?
            false // URLs?
            );

        // set chart background
        chart.setBackgroundPaint(Color.white);

        // set a few custom plot features
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setBackgroundPaint(new Color(0xffffe0));
        plot.setDomainGridlinesVisible(true);
        plot.setDomainGridlinePaint(Color.lightGray);
        plot.setRangeGridlinePaint(Color.lightGray);

        // set the plot's axes to display integers
        TickUnitSource ticks = NumberAxis.createIntegerTickUnits();
        NumberAxis domain = (NumberAxis) plot.getDomainAxis();
        domain.setStandardTickUnits(ticks);
        NumberAxis range = (NumberAxis) plot.getRangeAxis();
        range.setStandardTickUnits(ticks);

        // render shapes and lines
        XYLineAndShapeRenderer renderer =
            new XYLineAndShapeRenderer(true, true);
        plot.setRenderer(renderer);
        renderer.setBaseShapesVisible(true);
        renderer.setBaseShapesFilled(true);

        // set the renderer's stroke
        Stroke stroke = new BasicStroke(
            3f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL);
        renderer.setBaseOutlineStroke(stroke);

        // label the points
        NumberFormat format = NumberFormat.getNumberInstance();
        format.setMaximumFractionDigits(2);
              /*
        XYItemLabelGenerator generator =
            new StandardXYItemLabelGenerator(
                StandardXYItemLabelGenerator.DEFAULT_ITEM_LABEL_FORMAT,
                format, format);
        */
        ArrayList<Dummy> dd = new ArrayList<Dummy>();
        dd.add(new Dummy("wild cat",5.0));
        dd.add(new Dummy("tame dog", 4.0));
          dd.add(new Dummy("tiny lion", 6.0));

               XYItemLabelGenerator generator = new  MyItemLabelGenerator(dd);

        renderer.setBaseItemLabelGenerator(generator);
        renderer.setBaseItemLabelsVisible(true);

        return chart;
    }

    /** Main method */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFreeChartDemo demo = new JFreeChartDemo("JFreeChartDemo");
                demo.pack();
                demo.setLocationRelativeTo(null);
                demo.setVisible(true);
            }
         });
    }
}
class MyItemLabelGenerator extends StandardXYItemLabelGenerator {

    ArrayList <Dummy> dd;
    public MyItemLabelGenerator(ArrayList dd){
        super();
      this.dd = dd;
    }

public String generateLabel (XYDataset dataset, int series, int item){

   if(item == 0)return "           " + dd.get(item).getDescription();
   else if (item < 3) return dd.get(item).getDescription();
    else return "("+ series + "," + item + ")";


}


}

class Dummy {
    String description;
    double value;

    Dummy(String s, double v){
        description = s;
        value = v;
    }
    public String getDescription(){
        return description;
    }



}

Open in new window