Question

I try to create a customized legend in my chart but something strange happens when I display one or two legends. When I display 2 legends (the old one and the new one), everything is allright, colors are respected in legends and in the graph. But, when I want to display only the new legend, the colors in the legend are respected but the colors in the graph are not respected anymore.

This is an example on my issue: You have to comment and decomment a line to see the problem (see comments)

package org.jfree.chart.demo;

import java.awt.Color;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import javax.swing.JPanel;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.LegendItemSource;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.TimeSeriesDataItem;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RefineryUtilities;

public class Sample extends ApplicationFrame {

/**
 * 
 */
private static final long serialVersionUID = 1L;

private static ArrayList<Date> A;
private static ArrayList<Date> B;
private static ArrayList<Date> C;
private static Calendar t0;

public Sample(String paramString) {
    super(paramString);
    t0 = Calendar.getInstance();
    t0.set(2010, Calendar.JANUARY, 1);
    A = new ArrayList<Date>();
    B = new ArrayList<Date>();
    C = new ArrayList<Date>();
    JPanel localJPanel = createDemoPanel();
    setContentPane(localJPanel);

}

private static XYPlot createSubplot1(XYDataset paramXYDataset) {

    // With Dots
    XYLineAndShapeRenderer localXYLineAndShapeRenderer = new XYLineAndShapeRenderer();
    localXYLineAndShapeRenderer.setBaseLinesVisible(false);
    localXYLineAndShapeRenderer.setUseFillPaint(false);
    localXYLineAndShapeRenderer.setBaseFillPaint(Color.white);
    localXYLineAndShapeRenderer.setBaseShape(new Ellipse2D.Double(-4.0D,
            -4.0D, 8.0D, 8.0D));
    localXYLineAndShapeRenderer.setAutoPopulateSeriesShape(false);

    NumberAxis localNumberAxis = new NumberAxis("TEST");
    localNumberAxis.setVisible(false);
    localNumberAxis.setRange(0.5, 1.5);

    XYPlot localXYPlot = new XYPlot(paramXYDataset, new DateAxis("Time"),
            localNumberAxis, localXYLineAndShapeRenderer);

    return localXYPlot;

}

private static JFreeChart createChart() {
    CombinedDomainXYPlot localCombinedDomainXYPlot = new CombinedDomainXYPlot(
            new DateAxis("Time"));

    localCombinedDomainXYPlot.add(createSubplot1(createDataset1()), 1);

    JFreeChart localJFreeChart = new JFreeChart("Sample",
            localCombinedDomainXYPlot);
    localJFreeChart.getLegend().setPosition(RectangleEdge.TOP);
    localJFreeChart.getLegend().getItemContainer().getBlocks();

    localJFreeChart.setBackgroundPaint(Color.white);

    LegendItemCollection legendItemsOld = localCombinedDomainXYPlot
            .getLegendItems();
    final LegendItemCollection legendItemsNew = new LegendItemCollection();

    for (int i = 0; i < legendItemsOld.getItemCount(); i++) {
        legendItemsNew.add(legendItemsOld.get(i));
    }
    LegendItemSource source = new LegendItemSource() {
        LegendItemCollection lic = new LegendItemCollection();
        {
            lic.addAll(legendItemsNew);
        }

        public LegendItemCollection getLegendItems() {
            return lic;
        }
    };
    localJFreeChart.addLegend(new LegendTitle(source));

    ChartUtilities.applyCurrentTheme(localJFreeChart);

    ////////////////////////////////////////////////////////////////////////
    /**
     * If you comment the following line, two legends are displayed and the
     * colors in the graph are respected (yellow, red, blue, red, green)
     * However, when you decomment the line, only the new legend is
     * displayed. The legend is correct but the colors in the graph are not
     * respected anymore (red, yellow, green, yellow, blue)
     */
    /////////////////////////////////////////////////////////////////////////
    // localJFreeChart.getLegend().setVisible(false);



    return localJFreeChart;
}

public static JPanel createDemoPanel() {
    return new ChartPanel(createChart());
}

private static XYDataset createDataset1() {
    final Calendar out1 = Calendar.getInstance();
    out1.set(2009, Calendar.JANUARY, 1);

    final Calendar out2 = Calendar.getInstance();
    out2.set(2010, Calendar.JANUARY, 3);

    final Calendar end = Calendar.getInstance();
    end.set(2012, Calendar.SEPTEMBER, 30);

    Date date1 = date(t0, 0);
    TimeSeries s1 = new TimeSeries("RED");

    int i = 0;

    TimeSeries s4 = new TimeSeries("YELLOW");
    TimeSeries s2 = new TimeSeries("BLUE");
    TimeSeries s3 = new TimeSeries("GREEN");

    RegularTimePeriod rtpt0 = new FixedMillisecond(t0.getTime());
    TimeSeriesDataItem t = new TimeSeriesDataItem(rtpt0, 1);
    s4.add(t);
    i++;
    int interval = 57;
    date1 = date(t0, 0 + interval * i);
    Calendar d1;

    while (date1.before(date(end, 0))) {

        while (date1.before(date(end, 0)) && i < 8) {
            RegularTimePeriod rtp = new FixedMillisecond(date1.getTime());
            A.add(date1);
            t = new TimeSeriesDataItem(rtp, 1);
            s1.add(t);

            d1 = Calendar.getInstance();
            d1.setTimeInMillis(date1.getTime());
            date1 = date(d1, 0 + interval);
            i++;

        }

        if (date1.before(date(end, 0))) {
            RegularTimePeriod rtp = new FixedMillisecond(date1.getTime());
            B.add(date1);
            t = new TimeSeriesDataItem(rtp, 1);
            s2.add(t);
            d1 = Calendar.getInstance();
            d1.setTimeInMillis(date1.getTime());
            date1 = date(d1, 0 + interval);
        }
        d1 = Calendar.getInstance();
        d1.setTimeInMillis(date1.getTime());
        date1 = date(d1, 14);
        i = 1;
        while (date1.before(date(end, 0)) && i < 8) {
            RegularTimePeriod rtp = new FixedMillisecond(date1.getTime());
            A.add(date1);
            t = new TimeSeriesDataItem(rtp, 1);
            s1.add(t);
            d1 = Calendar.getInstance();
            d1.setTimeInMillis(date1.getTime());
            date1 = date(d1, 0 + interval);
            i++;

        }
        i = 0;
        if (date1.before(date(end, 0))) {
            RegularTimePeriod rtp = new FixedMillisecond(date1.getTime());
            C.add(date1);
            t = new TimeSeriesDataItem(rtp, 1);
            s3.add(t);
            d1 = Calendar.getInstance();
            d1.setTimeInMillis(date1.getTime());
            date1 = date(d1, 0 + interval);
        }
        d1 = Calendar.getInstance();
        d1.setTimeInMillis(date1.getTime());
        date1 = date(d1, 61);

    }

    TimeSeriesCollection dataset = new TimeSeriesCollection();

    dataset.addSeries(s1);
    dataset.addSeries(s2);
    dataset.addSeries(s3);
    dataset.addSeries(s4);
    return dataset;
}

/**
 * Utility method for creating <code>Date</code> objects.
 * 
 * @param day
 *            the date.
 * @param month
 *            the month.
 * @param year
 *            the year.
 * 
 * @return a date.
 */
private static Date date(Calendar calendar, int daysPlus) {
    final Calendar calendarResult = (Calendar) calendar.clone();
    calendarResult.add(Calendar.DAY_OF_MONTH, daysPlus);
    final Date result = calendarResult.getTime();

    return result;

}

public static void main(String[] paramArrayOfString) {
    Sample localXYTaskDatasetDemo2 = new Sample("Sample");
    localXYTaskDatasetDemo2.pack();
    RefineryUtilities.centerFrameOnScreen(localXYTaskDatasetDemo2);
    localXYTaskDatasetDemo2.setVisible(true);
}

}

Thanks for your help.

Was it helpful?

Solution

It was your call to ChartUtilities.applyCurrentTheme that overwrote the colors.

Another thing: You should use the chart.removeLegend() method when you need to remove the standard one. See the following code for the solution.

private static JFreeChart createChart() {
   CombinedDomainXYPlot localCombinedDomainXYPlot = new CombinedDomainXYPlot(new DateAxis("Time"));

   JFreeChart localJFreeChart = new JFreeChart("Sample", localCombinedDomainXYPlot);
   localCombinedDomainXYPlot.add(createSubplot1(createDataset1()), 1);
   ChartUtilities.applyCurrentTheme(localJFreeChart);
   localJFreeChart.setBackgroundPaint(Color.white);

   final LegendItemCollection legendItemsOld = localCombinedDomainXYPlot.getLegendItems();
   LegendItemSource source = new LegendItemSource() {
      public LegendItemCollection getLegendItems() {
         LegendItemCollection lic = new LegendItemCollection();
         int itemCount = legendItemsOld.getItemCount();
         for (int i = 0; i < itemCount; i++) {
            lic.add(legendItemsOld.get(i));
         }
         return lic;
      }
   };
   localJFreeChart.removeLegend();
   localJFreeChart.addLegend(new LegendTitle(source));
   localJFreeChart.getLegend().setPosition(RectangleEdge.TOP);
   localJFreeChart.getLegend().getItemContainer().getBlocks();

   return localJFreeChart;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top