问题描述
我正在尝试使用 JFreeChart ChartPanel
来删除面板边缘和图形本身之间不需要的额外空间.
I am trying to get a JFreeChart ChartPanel
to remove unwanted extra space between the edge of the panel and the graph itself.
为了最好地说明,这里有一个 SSCCE(安装了 JFreeChart):
To best illustrate, here's a SSCCE (with JFreeChart installed):
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
}
如果调整框架大小,您可以看到无法使图形的边缘到达面板的边缘(面板以红色勾勒出轮廓).尤其是在底部 - 图表底部和面板底部之间总是存在间隙.
If you resize the frame, you can see that you cannot make the edge of the graph go to the edge of the panel (the panels are outlined in red). Especially on the bottom - there is always a gap between the bottom the graph and the bottom of the panel.
有没有办法让图形填满整个区域?有没有办法至少保证它接触面板的一个边缘(即接触顶部和底部或左右)??
Is there a way to make the graph fill the entire area? Is there a way to at least guarantee that it is touching one edge of the panel (i.e., it is touching the top and bottom or the left and right) ??
推荐答案
仅供参考,在不改变情节的情况下,以下是以下设置的结果:
For reference, without changing the plot, here's the result with the following settings:
在封闭框架上调用
pack()
.
使用无间隙GridLayout
.
返回等边首选大小.
setMeterAngle(360);
.
setDrawBorder(true);
将尺寸调整为非方形会填充较窄的尺寸.
Resizing to a non-square aspect fills the narrower dimension.
附录:如此处所示,您可以覆盖图表的draw()
方法.为了在下面的变体中改进调整大小的行为,绘图的 draw()
方法被覆盖以将 area
移动其高度的一小部分.基于 getMeterAngle()
的函数也可能有用.
Addendum: As shown here, you can override the chart's draw()
method. For improved resizing behavior in the variation below, the plot's draw()
method is overridden to shift the area
by a fraction of its height. A function based on getMeterAngle()
may also be useful.
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
}
}
这篇关于摆脱 jfreechart 图表面板不必要的空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!