Search code examples
javajfreechart

StackedXYAreaChart - why does the series value get added?


enter image description here

I am plotting a stackedXYAreaChart. For the same time period, if I plot values for two different series, the second values is added to the first. Is that supposed to happen ? Why is that value for series 2 - 105 is actually extended to 185?

Here's my code:

package test;   

import java.awt.BorderLayout;   
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;   
import org.jfree.chart.*;   
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;   
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotOrientation;   
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;   
import org.jfree.chart.renderer.xy.StackedXYAreaRenderer2;   
import org.jfree.chart.renderer.xy.XYItemRendererState;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimePeriod;
import org.jfree.data.time.TimeTableXYDataset;
import org.jfree.data.xy.*;   

public class Test2   
{   

    private static final long serialVersionUID = 1L;   

    public Test2(String s)   
    {     
        JFreeChart jfreechart = createChart(createDataset());  
        JPanel jpanel = new ChartPanel(jfreechart);   
        JPanel masterPanel = new JPanel(new BorderLayout());
        masterPanel.add(jpanel, BorderLayout.CENTER);
        masterPanel.add(addUserControls(jfreechart), BorderLayout.EAST);
        JFrame frame = new JFrame();
        frame.add(masterPanel);
        frame.setBackground(Color.WHITE);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }   

    private static TimeTableXYDataset createDataset()   
    {   
        TimeTableXYDataset xyseries = new TimeTableXYDataset();

        xyseries.add(new Millisecond(), 5D, "Series 1");   
        xyseries.add(new Millisecond(), 10D, "Series 1");   
        xyseries.add(new Millisecond(), 15D, "Series 1");   
        xyseries.add(new Millisecond(), 20D, "Series 1");   

        xyseries.add(new Millisecond(), 15D, "Series 2");   
        xyseries.add(new Millisecond(), 20D, "Series 2");   
        xyseries.add(new Millisecond(), 25D, "Series 2");   
        xyseries.add(new Millisecond(), 30D, "Series 2");   

        TimePeriod period = new Millisecond();
        xyseries.add(period, 59, "Series 1");
        xyseries.add(period, 70, "Series 2");
        period = new Millisecond();
        xyseries.add(period, 85, "Series 1");
        xyseries.add(period, 105, "Series 2");

        return xyseries;   
    }   

    private static JFreeChart createChart(TableXYDataset tablexydataset)   
    {   
        JFreeChart jfreechart = ChartFactory.createStackedXYAreaChart("Stacked XY Area Chart Demo 1", "X Value", "Y Value", tablexydataset, PlotOrientation.VERTICAL, true, true, false);   
        XYPlot xyplot = (XYPlot)jfreechart.getPlot();   
        StackedXYAreaRenderer2 stackedxyarearenderer2 = new StackedXYAreaRenderer2() {
            public void drawItem(Graphics2D g2,
                     XYItemRendererState state,
                     Rectangle2D dataArea,
                     PlotRenderingInfo info,
                     XYPlot plot,
                     ValueAxis domainAxis,
                     ValueAxis rangeAxis,
                     XYDataset dataset,
                     int series,
                     int item,
                     CrosshairState crosshairState,
                     int pass) {
    if (!getItemVisible(series, item)) {
        return;
    }
    super.drawItem(g2, state, dataArea, info, plot, domainAxis, rangeAxis, dataset, series, item, crosshairState, pass);
    }
        };   
        stackedxyarearenderer2.setToolTipGenerator(new StandardXYToolTipGenerator());   
        xyplot.setRenderer(0, stackedxyarearenderer2);   
        return jfreechart;   
    }   

    public static JPanel createDemoPanel()   
    {   
        JFreeChart jfreechart = createChart(createDataset());   
        return new ChartPanel(jfreechart);   
    }   

    public static void main(String args[])   
    {   
        Test2 stackedxyareachartdemo1 = new Test2("Stacked XY Area Chart Demo 1");   
    }   

    public JPanel addUserControls(JFreeChart chartPlot) {
        JPanel userPanel = new JPanel(new GridLayout(2,2));
        JCheckBox Series0Button = new JCheckBox("Series 1");
        Series0Button.setSelected(true);
        Series0Button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                System.out.println("Series count" + chartPlot.getXYPlot().getSeriesCount());
                if (Series0Button.isSelected()) {
                StackedXYAreaRenderer2 renderer = (StackedXYAreaRenderer2) chartPlot.getXYPlot().getRenderer();
                renderer.setSeriesVisible(0, Boolean.TRUE, true);
                } else {
                    StackedXYAreaRenderer2 renderer = (StackedXYAreaRenderer2) chartPlot.getXYPlot().getRenderer();
                    renderer.setSeriesVisible(0, Boolean.FALSE, true);
                }
            }
        });

        JCheckBox series1Button = new JCheckBox("Series 2");
        series1Button.setSelected(true);
        series1Button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                if (series1Button.isSelected()) {
                StackedXYAreaRenderer2 renderer = (StackedXYAreaRenderer2) chartPlot.getXYPlot().getRenderer();
                renderer.setSeriesVisible(1, Boolean.TRUE, true);
                } else {
                    StackedXYAreaRenderer2 renderer = (StackedXYAreaRenderer2) chartPlot.getXYPlot().getRenderer();
                    renderer.setSeriesVisible(1, Boolean.FALSE, true);
                }
            }
        });
        userPanel.add(Series0Button);
        userPanel.add(series1Button);
        return userPanel;
    }
}    

Solution

  • Why is that the value for series 2105 is actually extended to 185?

    This "stacking" is the expected behavior of StackedXYAreaRenderer2. The actual range value is 190, which equals 85 + 105.

    xyseries.add(period, 85, "Series 1");
    xyseries.add(period, 105, "Series 2");
    

    The effect may be easier to see if you zoom in or add more data.

    Also, note that Swing GUI objects should be constructed and manipulated only on the event dispatch thread.