JFreechart 中的多个堆叠区域数据集

Multiple Stacked Area datasets in JFreechart

我正在使用 JFreechart,我正在尝试获得与 XYDifferenceRenderer 相似但 CategoryPlot 的内容。我 运行 感兴趣的问题是能够在同一个地块上绘制多个 StackedAreaRenderer。下面有一个看起来像浮动的 StackedArea。这就是我想要的。

package test;

import java.awt.Color;
import java.awt.Dimension;

import java.util.List;

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.CategoryLabelPositions;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.AreaRendererEndType;
import org.jfree.chart.renderer.category.StackedAreaRenderer;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import org.jfree.ui.RefineryUtilities;

/**
 *
 * @author buxk
 */
public class DifferenceWithCategories extends ApplicationFrame{


    public DifferenceWithCategories(String title){
        super(title);

        final JFreeChart chart = createChart();

        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new Dimension(500,270));
        setContentPane(chartPanel);

    }

    /**
     * Returns a sample dataset.
     *
     * @return The dataset.
     */
    private CategoryDataset createDataset1() {

        // row keys...
        String series1 = "First";

        // column keys...
        String category1 = "Category 1";
        String category2 = "Category 2";
        String category3 = "Category 3";
        String category4 = "Category 4";
        String category5 = "Category 5";

        // create the dataset...
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        dataset.addValue(4.0, series1, category1);
        dataset.addValue(4.0, series1, category2);
        dataset.addValue(3.0, series1, category3);
        dataset.addValue(5.0, series1, category4);
        dataset.addValue(5.0, series1, category5);

        return dataset;
    }


    /**
     * Returns a sample dataset.
     *
     * @return The dataset.
     */
    private CategoryDataset createDataset2() {

        // row keys...
        String series2 = "Second";

        // column keys...
        String category1 = "Category 1";
        String category2 = "Category 2";
        String category3 = "Category 3";
        String category4 = "Category 4";
        String category5 = "Category 5";

        // create the dataset...
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        dataset.addValue(5.0, series2, category1);
        dataset.addValue(7.0, series2, category2);
        dataset.addValue(6.0, series2, category3);
        dataset.addValue(8.0, series2, category4);
        dataset.addValue(6.0, series2, category5);

        return dataset;
    }


    /**
     * Returns a sample dataset.
     *
     * @return The dataset.
     */
    private CategoryDataset createDataset3() {

        // row keys...
        String series3 = "Third";

        // column keys...
        String category1 = "Category 1";
        String category2 = "Category 2";
        String category3 = "Category 3";
        String category4 = "Category 4";
        String category5 = "Category 5";

        // create the dataset...
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        dataset.addValue(1.0, series3, category1);
        dataset.addValue(3.0, series3, category2);
        dataset.addValue(2.0, series3, category3);
        dataset.addValue(3.0, series3, category4);
        dataset.addValue(4.0, series3, category5);

        return dataset;
    }

    private CategoryDataset merge4StackedDataset(CategoryDataset d1, CategoryDataset d2){

        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        List<Comparable> columnKeys = d1.getColumnKeys();
        List<Comparable> d1RowKeys = d1.getRowKeys();
        List<Comparable> d2RowKeys = d2.getRowKeys();
        double minValue, maxValue;
        for (Comparable columnKey : columnKeys) {
            for (Comparable rowKey : d1RowKeys) {
                for (Comparable d2RowKey : d2RowKeys) {
                    minValue = Math.min(d1.getValue(rowKey, columnKey).doubleValue(),d2.getValue(d2RowKey, columnKey).doubleValue());
                    maxValue = Math.max(d1.getValue(rowKey, columnKey).doubleValue(),d2.getValue(d2RowKey, columnKey).doubleValue());
                    dataset.addValue(minValue, rowKey, columnKey);
                    dataset.addValue(maxValue - minValue, d2RowKey, columnKey);
//                    dataset.addValue(d2.getValue(d2RowKey, columnKey).doubleValue(), d2RowKey, columnKey);
                }
            }

        }

        return dataset;
    }

    private JFreeChart createChart() {

        CategoryDataset dataset1 = merge4StackedDataset(createDataset1(), createDataset2());
        CategoryDataset dataset2 = merge4StackedDataset(createDataset1(), createDataset3());

        //create chart with empty dataset
        final JFreeChart chart = ChartFactory.createAreaChart(
                "Testing",
                "Categories",
                "Values",
                dataset1,
                PlotOrientation.VERTICAL,
                true,  // legend
                true,  // tool tips
                false  // URLs
        );

        //make the chart have a white background
        chart.setBackgroundPaint(Color.white);

        //get the chart's plot
        final CategoryPlot plot = chart.getCategoryPlot();

        //color the plot
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);

        //make a stacked area renderer for the first dataset
        final StackedAreaRenderer renderer1 = new StackedAreaRenderer();
        renderer1.setEndType(AreaRendererEndType.LEVEL);
        renderer1.setDefaultToolTipGenerator(new StandardCategoryToolTipGenerator());

        //turn off the first data set that lets the stack float
        renderer1.setSeriesPaint(0, new Color(Color.blue.getRed(), Color.blue.getGreen(), Color.blue.getBlue(), 0));
        renderer1.setSeriesVisibleInLegend(0, false);

        plot.setRenderer(0, renderer1);
        plot.setRenderer(1, renderer1);


//        plot.setDataset(2, dataset2);
//        final StackedAreaRenderer renderer2 = new StackedAreaRenderer();
//        renderer2.setEndType(AreaRendererEndType.LEVEL);
//        renderer2.setDefaultToolTipGenerator(new StandardCategoryToolTipGenerator());
//        renderer2.setSeriesPaint(2, new Color(Color.green.getRed(), Color.green.getGreen(), Color.green.getBlue(), 0));
//        renderer2.setSeriesVisibleInLegend(2, false);
//        renderer1.setSeriesPaint(2, new Color(Color.green.getRed(), Color.green.getGreen(), Color.green.getBlue(), 0));
//        renderer1.setSeriesPaint(3, new Color(Color.black.getRed(), Color.black.getGreen(), Color.black.getBlue(), 255));
//        renderer1.setSeriesVisibleInLegend(2, false);
//        plot.setRenderer(2, renderer2);
//        plot.setRenderer(3, renderer2);
//        plot.setRenderer(2, renderer1);
//        plot.setRenderer(3, renderer1);

        plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);
        plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
        plot.setDomainCrosshairVisible(true);
        plot.setRangeCrosshairVisible(true);

        return chart;
    }

    public static void main(String[] args) {
        final DifferenceWithCategories demo = new DifferenceWithCategories("Diference With Categories");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

    }
}

版本 1
如果我取消注释 dataset2renderer2 的代码部分,那么我会得到一些奇怪的结果,其中我有三个区域,图例中列出了三个项目。

版本 2
如果我取消注释 dataset2renderer1 的代码部分,我得到我认为接近我想要的东西,但是,两者的区域都是红色的,两者的图例都是 Second dataset2.

不存在

有谁知道我如何获得版本 1 的着色但版本 2 的区域集?

我找到了如何获得我正在寻找的东西。问题来自渲染器需要知道数据集相对于自身的索引与数据集相对于绘图的索引。
因此,当将渲染器添加到绘图时,使用相对于自身的数据集索引的第二个渲染器修复了它。

具有预期输出的代码:

import java.awt.Dimension;

import java.util.List;

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.CategoryLabelPositions;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.AreaRendererEndType;
import org.jfree.chart.renderer.category.StackedAreaRenderer;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import org.jfree.ui.RefineryUtilities;

/**
 *
 * @author lemming622
 */
public class DifferenceWithCategories extends ApplicationFrame{


    public DifferenceWithCategories(String title){
        super(title);

        final JFreeChart chart = createChart();

        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new Dimension(500,270));
        setContentPane(chartPanel);

    }

    /**
     * Returns a sample dataset.
     *
     * @return The dataset.
     */
    private CategoryDataset createDataset1() {

        // row keys...
        String series1 = "First";

        // column keys...
        String category1 = "Category 1";
        String category2 = "Category 2";
        String category3 = "Category 3";
        String category4 = "Category 4";
        String category5 = "Category 5";

        // create the dataset...
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        dataset.addValue(4.0, series1, category1);
        dataset.addValue(4.0, series1, category2);
        dataset.addValue(3.0, series1, category3);
        dataset.addValue(5.0, series1, category4);
        dataset.addValue(5.0, series1, category5);

        return dataset;
    }


    /**
     * Returns a sample dataset.
     *
     * @return The dataset.
     */
    private CategoryDataset createDataset2() {

        // row keys...
        String series2 = "Second";

        // column keys...
        String category1 = "Category 1";
        String category2 = "Category 2";
        String category3 = "Category 3";
        String category4 = "Category 4";
        String category5 = "Category 5";

        // create the dataset...
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        dataset.addValue(5.0, series2, category1);
        dataset.addValue(7.0, series2, category2);
        dataset.addValue(6.0, series2, category3);
        dataset.addValue(8.0, series2, category4);
        dataset.addValue(6.0, series2, category5);

        return dataset;
    }


    /**
     * Returns a sample dataset.
     *
     * @return The dataset.
     */
    private CategoryDataset createDataset3() {

        // row keys...
        String series3 = "Third";

        // column keys...
        String category1 = "Category 1";
        String category2 = "Category 2";
        String category3 = "Category 3";
        String category4 = "Category 4";
        String category5 = "Category 5";

        // create the dataset...
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        dataset.addValue(1.0, series3, category1);
        dataset.addValue(3.0, series3, category2);
        dataset.addValue(2.0, series3, category3);
        dataset.addValue(3.0, series3, category4);
        dataset.addValue(4.0, series3, category5);

        return dataset;
    }

    private CategoryDataset merge4StackedDataset(CategoryDataset d1, CategoryDataset d2){

        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        List<Comparable> columnKeys = d1.getColumnKeys();
        List<Comparable> d1RowKeys = d1.getRowKeys();
        List<Comparable> d2RowKeys = d2.getRowKeys();
        double minValue, maxValue;
        for (Comparable columnKey : columnKeys) {
            for (Comparable rowKey : d1RowKeys) {
                for (Comparable d2RowKey : d2RowKeys) {
                    minValue = Math.min(d1.getValue(rowKey, columnKey).doubleValue(),d2.getValue(d2RowKey, columnKey).doubleValue());
                    maxValue = Math.max(d1.getValue(rowKey, columnKey).doubleValue(),d2.getValue(d2RowKey, columnKey).doubleValue());
                    dataset.addValue(minValue, rowKey, columnKey);
                    dataset.addValue(maxValue - minValue, d2RowKey, columnKey);
//                    dataset.addValue(d2.getValue(d2RowKey, columnKey).doubleValue(), d2RowKey, columnKey);
                }
            }

        }

        return dataset;
    }

    private JFreeChart createChart() {

        CategoryDataset dataset1 = merge4StackedDataset(createDataset1(), createDataset2());
        CategoryDataset dataset2 = merge4StackedDataset(createDataset1(), createDataset3());

        //create chart with empty dataset
        final JFreeChart chart = ChartFactory.createAreaChart(
                "Testing",
                "Categories",
                "Values",
                dataset1,
                PlotOrientation.VERTICAL,
                true,  // legend
                true,  // tool tips
                false  // URLs
        );

        //make the chart have a white background
        chart.setBackgroundPaint(Color.white);

        //get the chart's plot
        final CategoryPlot plot = chart.getCategoryPlot();

        //color the plot
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);

        //make a stacked area renderer for the first dataset
        final StackedAreaRenderer renderer1 = new StackedAreaRenderer();
        renderer1.setEndType(AreaRendererEndType.LEVEL);
        renderer1.setDefaultToolTipGenerator(new StandardCategoryToolTipGenerator());

        //turn off the first data set that lets the stack float
        renderer1.setSeriesPaint(0, new Color(Color.blue.getRed(), Color.blue.getGreen(), Color.blue.getBlue(), 0));
        renderer1.setSeriesVisibleInLegend(0, false);

        plot.setRenderer(0, renderer1);
        plot.setRenderer(1, renderer1);


        plot.setDataset(2, dataset2);
        final StackedAreaRenderer renderer2 = new StackedAreaRenderer();
        renderer2.setEndType(AreaRendererEndType.LEVEL);
        renderer2.setDefaultToolTipGenerator(new StandardCategoryToolTipGenerator());
        renderer2.setSeriesPaint(0, new Color(Color.green.getRed(), Color.green.getGreen(), Color.green.getBlue(), 0));
        renderer2.setSeriesVisibleInLegend(0, false);
        plot.setRenderer(2, renderer2);
        plot.setRenderer(3, renderer2);

        plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);
        plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);
        plot.setDomainCrosshairVisible(true);
        plot.setRangeCrosshairVisible(true);

        return chart;
    }

    public static void main(String[] args) {
        final DifferenceWithCategories demo = new DifferenceWithCategories("Diference With Categories");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

    }
}