2

我试图让 JFreeChartChartPanel删除面板边缘和图形本身之间不需要的额外空间。

为了更好地说明,这是一个 SSCCE(安装了 JFreeChart):

public static void main(String[] args) {
    JPanel panel = new JPanel(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();

    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridwidth = 1;
    gbc.gridheight = 1;
    gbc.weightx = 1;
    gbc.weighty = 1;
    gbc.gridy = 1;

    gbc.gridx = 1;
    panel.add(createChart("Sales", Chart_Type.DOLLARS, 100000, 115000), gbc);
    gbc.gridx = 2;
    panel.add(createChart("Quotes", Chart_Type.DOLLARS, 250000, 240000), gbc);
    gbc.gridx = 3;
    panel.add(createChart("Profits", Chart_Type.PERCENTAGE, 40.00, 38.00), gbc);

    JFrame frame = new JFrame();
    frame.add(panel);
    frame.setSize(800, 300);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

private static ChartPanel createChart(String title, Chart_Type type, double goal, double actual) {
    double maxValue = goal * 2;
    double yellowToGreenNum = goal;
    double redToYellowNum = goal * .75;
    DefaultValueDataset dataset = new DefaultValueDataset(actual);

    JFreeChart jfreechart = createChart(dataset, Math.max(actual, maxValue), redToYellowNum, yellowToGreenNum, title, type);
    ChartPanel chartPanel = new ChartPanel(jfreechart);
    chartPanel.setBorder(new LineBorder(Color.red));
    return chartPanel;
}

private static JFreeChart createChart(ValueDataset valuedataset, Number maxValue, Number redToYellowNum, Number yellowToGreenNum, String title, Chart_Type type) {
    MeterPlot meterplot = new MeterPlot(valuedataset);
    meterplot.setRange(new Range(0.0D, maxValue.doubleValue()));
    meterplot.addInterval(new MeterInterval(" Goal Not Met ",
            new Range(0.0D, redToYellowNum.doubleValue()), Color.lightGray, new BasicStroke(2.0F),
            new Color(255, 0, 0, 128)));
    meterplot.addInterval(new MeterInterval(" Goal Almost Met ",
            new Range(redToYellowNum.doubleValue(), yellowToGreenNum.doubleValue()), Color.lightGray, new BasicStroke(2.0F),
            new Color(255, 255, 0, 64)));
    meterplot.addInterval(new MeterInterval(" Goal Met ",
            new Range(yellowToGreenNum.doubleValue(), maxValue.doubleValue()), Color.lightGray, new BasicStroke(2.0F),
            new Color(0, 255, 0, 64)));
    meterplot.setNeedlePaint(Color.darkGray);
    meterplot.setDialBackgroundPaint(Color.white);
    meterplot.setDialOutlinePaint(Color.gray);
    meterplot.setDialShape(DialShape.CHORD);
    meterplot.setMeterAngle(260);
    meterplot.setTickLabelsVisible(false);

    meterplot.setTickSize(maxValue.doubleValue() / 20);
    meterplot.setTickPaint(Color.lightGray);

    meterplot.setValuePaint(Color.black);
    meterplot.setValueFont(new Font("Dialog", Font.BOLD, 0));
    meterplot.setUnits("");
    if(type == Chart_Type.DOLLARS)
        meterplot.setTickLabelFormat(NumberFormat.getCurrencyInstance());
    else if(type == Chart_Type.PERCENTAGE)
        meterplot.setTickLabelFormat(NumberFormat.getPercentInstance());
    JFreeChart jfreechart = new JFreeChart(title,
            JFreeChart.DEFAULT_TITLE_FONT, meterplot, false);
    return jfreechart;
}

enum Chart_Type {
    DOLLARS,
    PERCENTAGE
}

如果您调整框架的大小,您会看到无法使图形的边缘到达面板的边缘(面板以红色勾勒)。特别是在底部 - 图表底部和面板底部之间总是存在间隙。

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

有没有办法让图表填满整个区域?有没有办法至少保证它正在触摸面板的一个边缘(即,它正在触摸顶部和底部或左侧和右侧)?

4

2 回答 2

4

作为参考,在不更改绘图的情况下,以下是具有以下设置的结果:

  • 调用pack()封闭框架。

  • 使用无间隙GridLayout

  • 返回等边的首选大小。

  • setMeterAngle(360);.

  • setDrawBorder(true);

调整到非方形方面会填充较窄的尺寸。

图片

附录:如此处所示,您可以覆盖图表的draw()方法。为了在下面的变体中改进调整大小的行为,绘图的draw()方法被覆盖以将其移动area其高度的一小部分。基于的函数getMeterAngle()也可能有用。

MeterPlot meterplot = new MeterPlot(valuedataset) {

    @Override
    public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo info) {
        double h = area.getHeight() * 6 / 5;
        area.setRect(area.getX(), area.getY(), area.getWidth(), h);
        super.draw(g2, area, anchor, parentState, info);
    }
};

图片

更新代码:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.DialShape;
import org.jfree.chart.plot.MeterInterval;
import org.jfree.chart.plot.MeterPlot;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.PlotState;
import org.jfree.data.Range;
import org.jfree.data.general.DefaultValueDataset;
import org.jfree.data.general.ValueDataset;

//* @see https://stackoverflow.com/a/25416067/230513 */
public class Test {

    public static void main(String[] args) {
        JPanel panel = new JPanel(new GridLayout());
        panel.add(createChart("Sales", Chart_Type.DOLLARS, 100000, 115000));
        panel.add(createChart("Quotes", Chart_Type.DOLLARS, 250000, 240000));
        panel.add(createChart("Profits", Chart_Type.PERCENTAGE, 40.00, 38.00));

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static ChartPanel createChart(String title, Chart_Type type, double goal, double actual) {
        double maxValue = goal * 2;
        double yellowToGreenNum = goal;
        double redToYellowNum = goal * .75;
        DefaultValueDataset dataset = new DefaultValueDataset(actual);

        JFreeChart jfreechart = createChart(dataset, Math.max(actual, maxValue), redToYellowNum, yellowToGreenNum, title, type);
        ChartPanel chartPanel = new ChartPanel(jfreechart) {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(300, 300);
            }
        };
        chartPanel.setBorder(new LineBorder(Color.red));
        return chartPanel;
    }

    private static JFreeChart createChart(ValueDataset valuedataset, Number maxValue, Number redToYellowNum, Number yellowToGreenNum, String title, Chart_Type type) {
        MeterPlot meterplot = new MeterPlot(valuedataset) {

            @Override
            public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo info) {
                double h = area.getHeight() * 6 / 5;
                area.setRect(area.getX(), area.getY(), area.getWidth(), h);
                super.draw(g2, area, anchor, parentState, info);
            }
        };
        meterplot.setRange(new Range(0.0D, maxValue.doubleValue()));
        meterplot.addInterval(new MeterInterval(" Goal Not Met ",
                new Range(0.0D, redToYellowNum.doubleValue()), Color.lightGray, new BasicStroke(2.0F),
                new Color(255, 0, 0, 128)));
        meterplot.addInterval(new MeterInterval(" Goal Almost Met ",
                new Range(redToYellowNum.doubleValue(), yellowToGreenNum.doubleValue()), Color.lightGray, new BasicStroke(2.0F),
                new Color(255, 255, 0, 64)));
        meterplot.addInterval(new MeterInterval(" Goal Met ",
                new Range(yellowToGreenNum.doubleValue(), maxValue.doubleValue()), Color.lightGray, new BasicStroke(2.0F),
                new Color(0, 255, 0, 64)));
        meterplot.setNeedlePaint(Color.darkGray);
        meterplot.setDialBackgroundPaint(Color.white);
        meterplot.setDialOutlinePaint(Color.gray);
        meterplot.setDialShape(DialShape.CHORD);
        meterplot.setMeterAngle(260);
        meterplot.setTickLabelsVisible(false);

        meterplot.setTickSize(maxValue.doubleValue() / 20);
        meterplot.setTickPaint(Color.lightGray);

        meterplot.setValuePaint(Color.black);
        meterplot.setValueFont(new Font("Dialog", Font.BOLD, 0));
        meterplot.setUnits("");
        if (type == Chart_Type.DOLLARS) {
            meterplot.setTickLabelFormat(NumberFormat.getCurrencyInstance());
        } else if (type == Chart_Type.PERCENTAGE) {
            meterplot.setTickLabelFormat(NumberFormat.getPercentInstance());
        }
        meterplot.setDrawBorder(true);
        meterplot.setDialShape(DialShape.CHORD);
        JFreeChart jfreechart = new JFreeChart(title,
                JFreeChart.DEFAULT_TITLE_FONT, meterplot, false);
        return jfreechart;
    }

    enum Chart_Type {

        DOLLARS,
        PERCENTAGE
    }
}
于 2014-08-20T23:25:54.117 回答
2

感谢trashgod的建议,我重写了JFreeChart::draw()将高度降低Rectangle2D chartArea50像素的方法(从技术上讲,我想我在高度上增加了50像素?不知道为什么会这样):

代码:

JFreeChart jfreechart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, meterplot, false) {
    @Override
    public void draw(Graphics2D g2, Rectangle2D chartArea, Point2D anchor, ChartRenderingInfo info) {
        chartArea.setRect(chartArea.getX(), chartArea.getY(), chartArea.getWidth(), chartArea.getHeight() + 50);
        super.draw(g2, chartArea, anchor, info);
    }
};

结果: 在此处输入图像描述

所以,感谢垃圾神帮助我指明了正确的方向。

编辑:后来,我仍然在图表的左侧和右侧遇到一些额外的空间。这段代码解决了这个问题:chartPanel.setMinimumDrawWidth(0);

于 2014-08-22T20:43:27.277 回答