工作中需要生成PDF 且包含图表。iText 或其他 可以访问网页地址转PDF。但是效果不是特别理想。故用iText代码方式实现生成PDF。奈何图表又是一个问题(还是个三角形的雷达图)。Java端生成的有好几个(Charts4j、JFreeChart还有几个忘记名字了)。最终选择了JFreeChart。生成图表图片文件后再插入PDF即可。iText使用内容整理后续更新。
Maven搭建项目引入JFreeChart
<!-- https://mvnrepository.com/artifact/org.jfree/jfreechart -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jfree/jcommon -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jcommon</artifactId>
<version>1.0.24</version>
</dependency>
继承SpiderWebPlot 实现带刻度雷达图
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.data.category.CategoryDataset;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.*;
import java.text.NumberFormat;
/**
* @Description 带刻度雷达图
* @className MySpiderWebPlot
* @Date 2019/7/16-11:15
**/
public class MySpiderWebPlot extends SpiderWebPlot {
private static final long serialVersionUID = 201907171429L;
private int ticks = DEFAULT_TICKS;
//默认刻度个数
private static final int DEFAULT_TICKS = 5;
private NumberFormat format = NumberFormat.getInstance();
//刻度显示的角度
private static final double PERPENDICULAR = 90;
//刻度的长度
private static final double TICK_SCALE = 0.010;
private int valueLabelGap = DEFAULT_GAP;
//刻度与刻度说明的间隔
private static final int DEFAULT_GAP = 10;
private static final double THRESHOLD = 15;
MySpiderWebPlot(CategoryDataset createCategoryDataset) {
super(createCategoryDataset);
}
@Override
protected void drawLabel(final Graphics2D g2, final Rectangle2D plotArea, final double value,
final int cat, final double startAngle, final double extent) {
super.drawLabel(g2, plotArea, value, cat, startAngle, extent);
final FontRenderContext frc = g2.getFontRenderContext();
final double[] transformed = new double[2];
final double[] transformer = new double[2];
final Arc2D arc1 = new Arc2D.Double(plotArea, startAngle, 0, Arc2D.OPEN);
for (int i = 1; i <= ticks; i++) {
final Point2D point1 = arc1.getEndPoint();
final double deltaX = plotArea.getCenterX();
final double deltaY = plotArea.getCenterY();
double labelX = point1.getX() - deltaX;
double labelY = point1.getY() - deltaY;
final double scale = ((double) i / (double) ticks);
final AffineTransform tx = AffineTransform.getScaleInstance(scale, scale);
final AffineTransform pointTrans = AffineTransform.getScaleInstance(scale + TICK_SCALE, scale + TICK_SCALE);
transformer[0] = labelX;
transformer[1] = labelY;
pointTrans.transform(transformer, 0, transformed, 0, 1);
final double pointX = transformed[0] + deltaX;
final double pointY = transformed[1] + deltaY;
tx.transform(transformer, 0, transformed, 0, 1);
labelX = transformed[0] + deltaX;
labelY = transformed[1] + deltaY;
double rotated = (PERPENDICULAR);
AffineTransform rotateTrans = AffineTransform.getRotateInstance(Math.toRadians(rotated), labelX, labelY);
transformer[0] = pointX;
transformer[1] = pointY;
rotateTrans.transform(transformer, 0, transformed, 0, 1);
final double x1 = transformed[0];
final double y1 = transformed[1];
rotated = (-PERPENDICULAR);
rotateTrans = AffineTransform.getRotateInstance(Math.toRadians(rotated), labelX, labelY);
rotateTrans.transform(transformer, 0, transformed, 0, 1);
final Composite saveComposite = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
g2.draw(new Line2D.Double(transformed[0], transformed[1], x1, y1));
if (startAngle == this.getStartAngle()) {
final String label = format.format(((double) i / (double) ticks) * this.getMaxValue());
final LineMetrics lm = getLabelFont().getLineMetrics(label, frc);
final double ascent = lm.getAscent();
if (Math.abs(labelX - plotArea.getCenterX()) < THRESHOLD) {
labelX += valueLabelGap;
labelY += ascent / (float) 2;
} else if (Math.abs(labelY - plotArea.getCenterY()) < THRESHOLD) {
labelY += valueLabelGap;
} else if (labelX >= plotArea.getCenterX()) {
if (labelY < plotArea.getCenterY()) {
labelX += valueLabelGap;
labelY += valueLabelGap;
} else {
labelX -= valueLabelGap;
labelY += valueLabelGap;
}
} else {
if (labelY > plotArea.getCenterY()) {
labelX -= valueLabelGap;
labelY -= valueLabelGap;
} else {
labelX += valueLabelGap;
labelY -= valueLabelGap;
}
}
g2.setPaint(getLabelPaint());
g2.setBackground(Color.green);
g2.setFont(getLabelFont());
g2.drawString(label, (float) labelX, (float) labelY);
}
g2.setComposite(saveComposite);
}
}
}
新建图表对象生成和数据组装方法
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.data.category.DefaultCategoryDataset;
import java.awt.*;
/**
* @Description 带刻度三角雷达图 自定义文字风格 背景色
* @className Test
* @Date 2019/7/16-11:16
**/
public class Test {
/**
* @Description 创建图表对象
* @Author 小帅丶
* @Date 2019/7/17 14:32
* @return org.jfree.chart.JFreeChart
**/
public static JFreeChart createChart() {
MySpiderWebPlot spiderwebplot = new MySpiderWebPlot(createDataset());
Font font = new Font("SansSerif", Font.BOLD,24);
JFreeChart jfreechart = new JFreeChart("", font,spiderwebplot, false);
//获取图表对象 对图表进行额外处理
SpiderWebPlot plot = (SpiderWebPlot) jfreechart.getPlot();
//设置图表文字
plot.setLabelFont(font);
//设置图表背景色
plot.setSeriesPaint(Color.green);
return jfreechart;
}
/**
* @Description 组装测试数据
* @Author 小帅丶
* @Date 2019/7/17 14:31
* @return org.jfree.data.category.DefaultCategoryDataset
**/
public static DefaultCategoryDataset createDataset() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
String group1 = "失信等级统计";
//value就是数据值
dataset.addValue(20,group1, "低危");
dataset.addValue(2, group1, "高危");
dataset.addValue(4, group1, "中危");
return dataset;
}
}
在SWING中显示图表
public class Test {
public static void main(String args[]) {
//在SWING中显示
JFrame jf = new JFrame();
jf.add(erstelleSpinnenDiagramm());
jf.pack();
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jf.setVisible(true);
}
/**
* @Description 图表放C/S面板
* @Author 小帅丶
* @Date 2019/7/17 14:32
* @Param []
* @return javax.swing.JPanel
**/
public static JPanel erstelleSpinnenDiagramm() {
JFreeChart jfreechart =createChart();
ChartPanel chartpanel = new ChartPanel(jfreechart);
return chartpanel;
}
}
效果图
将图表保存为图片文件
public class Test {
public static void main(String args[]) {
//将JFreeChart保存为图片存在文件路径中
saveAsFile("E:/JfreeChart/MySpiderWebPlot.png",400,300);
}
/**
* @Description 保存为图片
* @Author 小帅丶
* @Date 2019/7/17 14:41
* @param outputPath 图片保存路径
* @param weight 宽度
* @param height 高度
* @return void
**/
public static void saveAsFile(String outputPath, int weight, int height) {
FileOutputStream out = null;
try {
File outFile = new File(outputPath);
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
out = new FileOutputStream(outputPath);
// 保存为PNG
ChartUtils.writeChartAsPNG(out, createChart(),weight, height);
// 保存为JPEG
// ChartUtilities.writeChartAsJPEG(out, chart, 500, 400);
out.flush();
}catch (Exception e) {
System.out.println("异常 = " + e.getMessage());
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
System.out.println("异常 = " + e.getMessage());
}
}
}
}
}
图片效果图
多个group效果图
//设置图表背景色 多个
plot.setSeriesPaint(0,Color.blue );
plot.setSeriesPaint(1,Color.cyan );