如何使用XYBarRenderer在XYPlot上的条形图上绘制一条短线?

时间:2014-09-10 18:36:12

标签: java jfreechart oxyplot

我目前正在使用JFreeChartXYPlotXYBarRenderer来绘制水平条形图。我需要在图形中的每个条形图上绘制一条直线条的宽度,就像这样(红线):

Example bar graph

那些红线与蓝色条纹的大小不完全相同,这很好,它只是无法覆盖整个图形。 我一直在寻找张贴到this问题的答案,我一直在尝试使用XYBarRenderer.draw ...和XYBarRenderer.add ......无济于事。

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

作为替代方案,请考虑使用BoxAndWhiskerRenderer,图示为heresetMeanVisible(false)默认情况下会显示中位数。我没有尝试过,但setWhiskerWidth(0)和每个BoxAndWhiskerItem的合适值都应该抑制胡须和异常值。

image

答案 1 :(得分:2)

理想情况下,在JFreeChart中,您可以使用实现IntervalCategoryDataset界面的数据集和可以直接从该数据渲染条形和中间标记的渲染器来创建此图表。但是,该数据集界面的主要实现使用起来有点麻烦,并且没有渲染器可以精确绘制您正在寻找的可视化表示。

下一个最好的事情(我能想到的)是使用重叠图表,它允许中间标记覆盖在条形图的顶部 - 这需要两个数据集和两个渲染器。结果如下(源代码如下):

enter image description here

/* =======================
 * OverlaidChartDemo1.java
 * =======================
 *
 * Copyright (c) 2014, Object Refinery Limited.
 * All rights reserved.
 *
 * http://www.jfree.org/jfreechart/index.html
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   - Neither the name of the Object Refinery Limited nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL OBJECT REFINERY LIMITED BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   -;
 *
 * Changes
 * -------
 * 10-Sep-2014 : Version 1 (DG);
 * 
 */

package org.jfree.chart.demo;

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

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.IntervalBarRenderer;
import org.jfree.chart.renderer.category.LevelRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.category.DefaultIntervalCategoryDataset;
import org.jfree.data.category.IntervalCategoryDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

/**
 * A sample application for the Stack Overflow question 
 * http://stackoverflow.com/questions/25772655/how-do-i-draw-a-short-line-over-a-bar-on-an-xyplot-using-xybarrenderer.
 */
public class OverlaidChartDemo1 extends ApplicationFrame {

    /**
     * Creates a new demo instance.
     *
     * @param title  the frame title.
     */
    public OverlaidChartDemo1(String title) {
        super(title);
        CategoryDataset dataset = createDataset1();
        JFreeChart chart = createChart(dataset);
        ChartPanel chartPanel = new ChartPanel(chart, false);
        chartPanel.setFillZoomRectangle(true);
        chartPanel.setMouseWheelEnabled(true);
        chartPanel.setPreferredSize(new Dimension(600, 480));
        setContentPane(chartPanel);
    }

    private static IntervalCategoryDataset createDataset1() {
        double[] start = new double[] { -4.1, -2.2, -2.1, -1.2, -0.4, 
                -0.2, -0.1, -0.15, 0, -0.1, -0.1, 0, 0, 0, 0 };
        double[] end = new double[] { 2.9, 3.6, 3.3, 2.5, 2.8, 2, 2.1, 2, 2, 
                1.8, 1.7, 1.8, 1.6, 1.2, 1.2 };
        DefaultIntervalCategoryDataset dataset 
                = new DefaultIntervalCategoryDataset(new double[][]{ start }, 
                        new double[][]{ end });
        dataset.setCategoryKeys(new String[] { "Dedicated Short Bias",
                "Managed Futures", "S&P 500", "Long/Short Equity", 
                "Emerging Markets", "Convertible Arbitrage", 
                "Event Driven - Multi Strategy", "Event Driven", 
                "DJ/Credit Suisse Hedge Fund Index", 
                "Event Driven - Distressed", "Multi-Strategy", "Global Macro", 
                "Fixed Income Arbitrage", "Event Driven - Risk Arbitrage",
                "Equity Market Neutral"});
        return dataset;
    }

    private static CategoryDataset createDataset2() {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        dataset.addValue(-1.3, "S1", "Dedicated Short Bias");
        dataset.addValue(0.7, "S1", "Managed Futures");
        dataset.addValue(1.2, "S1", "S&P 500");
        dataset.addValue(1.1, "S1", "Long/Short Equity");
        dataset.addValue(1.4, "S1", "Emerging Markets");
        dataset.addValue(1.05, "S1", "Convertible Arbitrage");
        dataset.addValue(1.2, "S1", "Event Driven - Multi Strategy");
        dataset.addValue(1.1, "S1", "Event Driven");
        dataset.addValue(0.7, "S1", "DJ/Credit Suisse Hedge Fund Index");
        dataset.addValue(1, "S1", "Event Driven - Distressed");
        dataset.addValue(0.8, "S1", "Multi-Strategy");
        dataset.addValue(1.2, "S1", "Global Macro");
        dataset.addValue(0.8, "S1", "Fixed Income Arbitrage");
        dataset.addValue(0.5, "S1", "Event Driven - Risk Arbitrage");
        dataset.addValue(0.6, "S1", "Equity Market Neutral");
        return dataset;
    }

    /**
     * Creates a sample chart.
     *
     * @param dataset  the dataset.
     *
     * @return The chart.
     */
    private static JFreeChart createChart(CategoryDataset dataset) {
        CategoryAxis xAxis = new CategoryAxis(null);
        ValueAxis yAxis = new NumberAxis("Monthly Return (%)");
        IntervalBarRenderer renderer = new IntervalBarRenderer();
        renderer.setBarPainter(new StandardBarPainter());
        renderer.setSeriesPaint(0, new Color(10, 12, 118));
        renderer.setShadowVisible(false);
        CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
        plot.setOrientation(PlotOrientation.HORIZONTAL);
        plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
        plot.setBackgroundPaint(new Color(230, 230, 230));
        plot.setRangeGridlinePaint(Color.WHITE);
        plot.setRangeGridlineStroke(new BasicStroke(0.5f));

        // overlay a second dataset
        plot.setDataset(1, createDataset2());
        LevelRenderer renderer2 = new LevelRenderer();
        renderer2.setSeriesStroke(0, new BasicStroke(4.0f, 
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        renderer2.setSeriesPaint(0, Color.RED);
        plot.setRenderer(1, renderer2);
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);

        JFreeChart chart = new JFreeChart(
                "Interquartile Range and Median: Monthly Returns", plot);
        chart.removeLegend();
        chart.setBackgroundPaint(Color.WHITE);
        return chart;
    }

    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {
        OverlaidChartDemo1 demo = new OverlaidChartDemo1(
                "JFreeChart: OverlaidChartDemo1.java");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}