工作中需要生成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 );