摆脱jfreechart chartpanel不必要的空间

时间:2014-08-20 22:17:32

标签: java swing jfreechart chartpanel

我正在尝试使用JFreeChart ChartPanel来删除面板边缘和图形本身之间不需要的额外空间。

为了更好地说明,这是一个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
}

如果调整框架大小,则可以看到无法使图形边缘移动到面板边缘(面板以红色标出)。特别是在底部 - 图表底部和面板底部之间总是存在间隙。

enter image description here

enter image description here

enter image description here

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

2 个答案:

答案 0 :(得分:4)

作为参考,在不更改图表的情况下,通过以下设置得出结果:

  • 在封闭框架上调用pack()

  • 使用无间隙GridLayout

  • 返回等边的首选尺寸。

  • setMeterAngle(360);

  • setDrawBorder(true);

调整为非方形方面会填充较窄的维度。

image

附录:如图here所示,您可以覆盖图表的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);
    }
};

image

更新的代码:

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
    }
}

答案 1 :(得分:2)

感谢trashgod的建议,我覆盖了JFreeChart::draw()方法,将Rectangle2D chartArea的高度减少了50个像素(从技术上讲,我想我在高度上加了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);
    }
};

结果: enter image description here

所以,感谢trashgod帮助我指明正确的方向。

编辑:之后,我仍然在图表的左侧和右侧遇到一些额外的空间。这是通过以下代码解决的:chartPanel.setMinimumDrawWidth(0);