java - 具有多个类别的箱线图的 JFreeChart 缩放

标签 java charts scaling jfreechart boxplot

我目前正在开发一个基于 Java 的项目,使用 JFreeChart 来显示箱线图。

我的问题是如何显示包含 CategoryDataset 箱线图的图表,该 CategoryDataset 有大约 20 个类别和 5+ 个系列。

目前,如果未设置 ChartPanel 的首选大小,图例、标签和注释是可读的,但箱线图太小。或者设置 ChartPanel 的大小,使箱线图具有可接受的大小,但随后水平拉伸(stretch)图例、标签和注释。

我的问题是,如何在不缩放图表的图例、轴标签和注释的情况下正确缩放箱线图?是否可以在不缩放图表的所有元素的情况下缩放绘图?

代码示例

import java.awt.Color;
import java.awt.Dimension;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JFrame;
import javax.swing.JScrollPane;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;


public class StretchedBoxAndWhiskerExample{

DefaultBoxAndWhiskerCategoryDataset dataset;
JFreeChart chart;
ChartPanel chartPanel;
JFrame frame;
JScrollPane scrollPane;

public StretchedBoxAndWhiskerExample() {
    createCategoryBoxplot();

    frame = new JFrame();
    scrollPane = new JScrollPane(chartPanel);
    scrollPane.setPreferredSize(new Dimension(800,700));
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    frame.add(scrollPane);
    frame.pack();
    frame.setVisible(true);
}

private void createCategoryBoxplot(){   
    dataset = createCategoryDataset();
    CategoryAxis xAxis = new CategoryAxis("");
    NumberAxis yAxis = new NumberAxis("Score");

    BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
    CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
    createJFreeChart(plot,"Test");

    // Design
    renderer.setFillBox(false);
    renderer.setMeanVisible(false);

    chart.setBackgroundPaint(Color.white); 
    plot.setBackgroundPaint(Color.lightGray); 
    plot.setDomainGridlinePaint(Color.white); 
    plot.setDomainGridlinesVisible(true); 
    plot.setRangeGridlinePaint(Color.white);
    plot.getRangeAxis().setRange(-10.5, 10.5);


    chartPanel = new ChartPanel(chart);
    chartPanel.setPreferredSize(new Dimension(3250,600));
}

private DefaultBoxAndWhiskerCategoryDataset createCategoryDataset() {

    dataset = new DefaultBoxAndWhiskerCategoryDataset();
    ArrayList<Double> values = createSampleData();
    ArrayList<String> categories = createSampleCategories();
    for (int i=0;i<=5;i++){
        for (String category : categories){
            dataset.add(values,i,category);
        }
    }
    return dataset;
}


private ArrayList<String> createSampleCategories() {
    ArrayList<String> tmp = new ArrayList<String>();
    for (int i=0;i<=20;i++){
        tmp.add("Category"+i);
    }
    return tmp;
}

private ArrayList<Double> createSampleData() {
    ArrayList<Double> tmp = new ArrayList<Double>();
    for (int i=0;i<10;i++){
        tmp.add(5.0);
        tmp.add(7.0);
        tmp.add(2.0);
        tmp.add(4.0);
    }
    return tmp;
}

private void createJFreeChart(CategoryPlot plot, String title){
    chart = new JFreeChart(title, plot);
}

public static void main(String[] args) throws IOException { 
    StretchedBoxAndWhiskerExample demo = new StretchedBoxAndWhiskerExample();

}
}

最佳答案

设置包含 ChartPanel 的首选大小,而不是图表,如图所示 herehere .

附录:我认为您无法将图表添加到滚动 Pane 中。相反,创建一个类似于 SlidingCategoryDataset 的类实现了 BoxAndWhiskerCategoryDataset。将滚动条添加到控制第一个显示索引的框架。

附录:一种不那么雄心勃勃的方法是使用一些合适的控件简单地对数据集的一部分进行分页,如下例所示。

enter image description here

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;

/** @see https://stackoverflow.com/questions/6844759 */
public class BoxAndWhiskerDemo {

    private static final int COLS = 20;
    private static final int VISIBLE = 4;
    private static final int ROWS = 5;
    private static final int VALUES = 10;
    private static final Random rnd = new Random();
    private List<String> columns;
    private List<List<List<Double>>> data;
    private DefaultBoxAndWhiskerCategoryDataset dataset;
    private CategoryPlot plot;
    private ChartPanel chartPanel;
    private JPanel controlPanel;
    private int start = 0;

    public BoxAndWhiskerDemo() {
        createData();
        createDataset(start);
        createChartPanel();
        createControlPanel();
    }

    private void createData() {
        columns = new ArrayList<String>(COLS);
        data = new ArrayList<List<List<Double>>>();
        for (int i = 0; i < COLS; i++) {
            String name = "Category" + String.valueOf(i + 1);
            columns.add(name);
            List<List<Double>> list = new ArrayList<List<Double>>();
            for (int j = 0; j < ROWS; j++) {
                list.add(createValues());
            }
            data.add(list);
        }
    }

    private List<Double> createValues() {
        List<Double> list = new ArrayList<Double>();
        for (int i = 0; i < VALUES; i++) {
            list.add(rnd.nextGaussian());
        }
        return list;
    }

    private void createDataset(int start) {
        dataset = new DefaultBoxAndWhiskerCategoryDataset();
        for (int i = start; i < start + VISIBLE; i++) {
            List<List<Double>> list = data.get(i);
            int row = 0;
            for (List<Double> values : list) {
                String category = columns.get(i);
                dataset.add(values, "s" + row++, category);
            }
        }
    }

    private void createChartPanel() {
        CategoryAxis xAxis = new CategoryAxis("Category");
        NumberAxis yAxis = new NumberAxis("Value");
        BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
        plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
        JFreeChart chart = new JFreeChart("BoxAndWhiskerDemo", plot);
        chartPanel = new ChartPanel(chart);
    }

    private void createControlPanel() {
        controlPanel = new JPanel();
        controlPanel.add(new JButton(new AbstractAction("\u22b2Prev") {

            @Override
            public void actionPerformed(ActionEvent e) {
                start -= VISIBLE;
                if (start < 0) {
                    start = 0;
                    return;
                }
                createDataset(start);
                plot.setDataset(dataset);
            }
        }));
        controlPanel.add(new JButton(new AbstractAction("Next\u22b3") {

            @Override
            public void actionPerformed(ActionEvent e) {
                start += VISIBLE;
                if (start > COLS - VISIBLE) {
                    start = COLS - VISIBLE;
                    return;
                }
                createDataset(start);
                plot.setDataset(dataset);
            }
        }));
    }

    public ChartPanel getChartPanel() {
        return chartPanel;
    }

    public JPanel getControlPanel() {
        return controlPanel;
    }

    public static void main(String[] args) throws IOException {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                BoxAndWhiskerDemo demo = new BoxAndWhiskerDemo();
                frame.add(demo.getChartPanel(), BorderLayout.CENTER);
                frame.add(demo.getControlPanel(), BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

关于java - 具有多个类别的箱线图的 JFreeChart 缩放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6844759/

相关文章:

java - 在 viewpager fragment 中添加按钮并在另一个 Activity 中添加 Intent ?

c# - 使用 CultureInfo 格式化 C# 图表轴

c# - 在没有 Draw() 的情况下缩放 Texture2D

Java - JEditorPane - 超链接问题

java - 使用 Selenium Java 在窗口屏幕中调整对象

java - 如何确定应用程序何时开始使用 java 反射已完成

带有组合图表的 iOS Swift Chart

javascript - 在 Google 圆环图中隐藏切片

c# - 如何缩小(缩放)整个图形结构?

java - 如何根据按下的按钮实例化不同大小的图标java