我正在尝试使用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
}
如果调整框架大小,则可以看到无法使图形边缘移动到面板边缘(面板以红色标出)。特别是在底部 - 图表底部和面板底部之间总是存在间隙。
有没有办法让图表填满整个区域?有没有办法至少保证它接触面板的一个边缘(即,它接触顶部和底部或左右两侧)??
答案 0 :(得分:4)
作为参考,在不更改图表的情况下,通过以下设置得出结果:
在封闭框架上调用pack()
。
使用无间隙GridLayout
。
返回等边的首选尺寸。
setMeterAngle(360);
。
setDrawBorder(true);
调整为非方形方面会填充较窄的维度。
附录:如图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);
}
};
更新的代码:
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);
}
};
结果:
所以,感谢trashgod帮助我指明正确的方向。
编辑:之后,我仍然在图表的左侧和右侧遇到一些额外的空间。这是通过以下代码解决的:chartPanel.setMinimumDrawWidth(0);