一,需求描述 使用Java生成饼图、条形图、折线图、XY图、3D图/条形图、气泡图、时间序列图并保存图片(png格式)
二,依赖版本情况 Java JDK21 + SpringBoot 3.3.3 + JfreeChart 1.5.3,POM依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.3</version>
<relativePath/>
</parent>
<groupId>org.example</groupId>
<artifactId>map_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.3</version>
</dependency>
</dependencies>
</project>
三,代码实现
柱状图/条形图
package org.example.map;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.ui.TextAnchor;
import org.jfree.data.category.DefaultCategoryDataset;
/**
* 柱状图/条形图
*/
public class BarChart_AWT {
public static void main(String[] args) {
// 1. 创建数据集
DefaultCategoryDataset dataset = createDataset();
// 2. 创建柱状图
JFreeChart barChart = createChart(dataset);
// 3. 保存为图片
String filePath = "bar_chart_output.png";
try {
ChartUtils.saveChartAsPNG(new File(filePath), barChart, 800, 600);
System.out.println("柱状图已保存至: " + new File(filePath).getAbsolutePath());
} catch (IOException e) {
System.err.println("保存图表时发生错误: " + e.getMessage());
}
}
private static DefaultCategoryDataset createDataset() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
// 添加数据(示例)
dataset.addValue(15, "分组1", "IPhone 5s");
dataset.addValue(20, "分组1", "SamSung Grand");
dataset.addValue(40, "分组1", "MotoG");
dataset.addValue(10, "分组1", "Nokia Lumia");
dataset.addValue(34, "分组2", "IPhone 5s");
dataset.addValue(68, "分组2", "SamSung Grand");
dataset.addValue(56, "分组2", "MotoG");
dataset.addValue(90, "分组2", "Nokia Lumia");
dataset.addValue(21, "分组3", "IPhone 5s");
dataset.addValue(32, "分组3", "SamSung Grand");
dataset.addValue(54, "分组3", "MotoG");
dataset.addValue(68, "分组3", "Nokia Lumia");
return dataset;
}
private static JFreeChart createChart(DefaultCategoryDataset dataset) {
JFreeChart chart = ChartFactory.createBarChart(
null, // 标题由后续设置
"种类", // X轴标签
"销量情况", // Y轴标签
dataset, // 数据集
PlotOrientation.VERTICAL,
true, true, false
);
CategoryPlot plot = chart.getCategoryPlot();
// 设置中文字体
Font font = new Font("SimSun", Font.PLAIN, 12); // 使用宋体
// 设置带字体的标题
chart.setTitle(new TextTitle("学校数量 vs 年份", font));
plot.setNoDataMessage("无数据");
// 设置坐标轴标签字体
plot.getDomainAxis().setLabelFont(font);
plot.getRangeAxis().setLabelFont(font);
// 设置图例字体以支持中文
chart.getLegend().setItemFont(font);
// 设置绘图区字体(如横纵坐标值)
plot.getDomainAxis().setTickLabelFont(font);
plot.getRangeAxis().setTickLabelFont(font);
// 设置每个分组的颜色(series index 从 0 开始)
plot.getRenderer().setSeriesPaint(0, new Color(255, 99, 71)); // 番茄红 - 分组1
plot.getRenderer().setSeriesPaint(1, new Color(30, 144, 255)); // 道奇蓝 - 分组2
plot.getRenderer().setSeriesPaint(2, new Color(50, 205, 50)); // 苹果绿 - 分组3
// ✅ 开启柱子上显示数值
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setDefaultItemLabelsVisible(true); // 显示标签
renderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());//指定value值,即纵坐标
renderer.setDefaultItemLabelFont(font); // 设置标签字体
renderer.setDefaultItemLabelPaint(Color.BLACK); // 设置标签颜色
renderer.setDefaultPositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.TOP_CENTER));
return chart;
}
}
气泡图
package org.example.map;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.xy.DefaultXYZDataset;
import java.awt.*;
import java.io.File;
import java.io.IOException;
/**
* 气泡图
*/
public class BubbleChart_AWT {
public static void main(String[] args) {
// 创建数据集
DefaultXYZDataset defaultxyzdataset = new DefaultXYZDataset();
double[] ad = { 30 , 40 , 50 , 60 , 70 , 80 };
double[] ad1 = { 10 , 20 , 30 , 40 , 50 , 60 };
double[] ad2 = { 4 , 5 , 10 , 8 , 9 , 6 };
double[][] ad3 = { ad , ad1 , ad2 };
double[] bd = { 10 , 30 , 40 , 20 , 50 , 100 };
double[] bd1 = { 20 , 60 , 30 , 60 , 70 , 120 };
double[] bd2 = { 23 , 1 , 67 , 34 , 56 , 87 };
double[][] bd3 = { bd , bd1 , bd2 };
defaultxyzdataset.addSeries( "种类1" , ad3 );
defaultxyzdataset.addSeries( "种类2" , bd3 );
JFreeChart chart = ChartFactory.createBubbleChart(
null,
"重量",
"年龄",
defaultxyzdataset,
PlotOrientation.HORIZONTAL,
true, true, false);
XYPlot plot = (XYPlot)chart.getPlot( );
plot.setForegroundAlpha( 0.65F );
XYItemRenderer xyitemrenderer = plot.getRenderer( );
//设置颜色
xyitemrenderer.setSeriesPaint( 0 , Color.blue );
xyitemrenderer.setSeriesPaint( 1 , Color.RED );
NumberAxis numberaxis = ( NumberAxis )plot.getDomainAxis( );
numberaxis.setLowerMargin( 0.2 );
numberaxis.setUpperMargin( 0.5 );
NumberAxis numberaxis1 = (NumberAxis)plot.getRangeAxis( );
numberaxis1.setLowerMargin( 0.8 );
numberaxis1.setUpperMargin( 0.9 );
// 设置图片尺寸
int width = 560;
int height = 367;
// 设置中文字体
Font font = new Font("SimSun", Font.PLAIN, 16); // 使用宋体
// 设置带字体的标题
chart.setTitle(new TextTitle("气泡图", font));
// 设置图例字体
chart.getLegend().setItemFont(font);
// 设置坐标轴标签字体
plot.getDomainAxis().setLabelFont(font);
plot.getRangeAxis().setLabelFont(font);
// 设置坐标轴刻度字体
plot.getDomainAxis().setTickLabelFont(font);
plot.getRangeAxis().setTickLabelFont(font);
// 保存为PNG文件
File outputFile = new File("Bubble Chart.png");
try {
ChartUtils.saveChartAsPNG(outputFile ,chart, width ,height);
System.out.println("气泡图已保存至: " + outputFile.getAbsolutePath());
} catch (IOException e) {
System.err.println("保存图表时发生错误: " + e.getMessage());
}
}
}
折线图
package org.example.map;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.chart.plot.PlotOrientation;
import java.awt.*;
import java.io.File;
import java.io.IOException;
/**
* 折线图
*/
public class LineChart_AWT {
public static void main(String[] args) {
// 创建数据集
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
//学校数量
dataset.addValue(15, "学校数量", "1970");
dataset.addValue(30, "学校数量", "1980");
dataset.addValue(60, "学校数量", "1990");
dataset.addValue(120, "学校数量", "2000");
dataset.addValue(240, "学校数量", "2010");
dataset.addValue(300, "学校数量", "2014");
// 教师数量
dataset.addValue(150, "教师数量", "1970");
dataset.addValue(300, "教师数量", "1980");
dataset.addValue(600, "教师数量", "1990");
dataset.addValue(1200, "教师数量", "2000");
dataset.addValue(2400, "教师数量", "2010");
dataset.addValue(3000, "教师数量", "2014");
// 创建折线图
JFreeChart chart = ChartFactory.createLineChart(
null, // 标题由后续设置
"年份", // X轴标签
"种类", // Y轴标签
dataset,
PlotOrientation.VERTICAL,
true, true, false);
// 设置图片尺寸
int width = 560;
int height = 367;
// 设置中文字体
Font font = new Font("SimSun", Font.PLAIN, 16); // 使用宋体
// 设置带字体的标题
chart.setTitle(new TextTitle("折线图", font));
// 设置图例字体
chart.getLegend().setItemFont(font);
// 设置坐标轴标签字体
CategoryPlot plot = chart.getCategoryPlot();
plot.getDomainAxis().setLabelFont(font);
plot.getRangeAxis().setLabelFont(font);
// 设置坐标轴刻度字体
plot.getDomainAxis().setTickLabelFont(font);
plot.getRangeAxis().setTickLabelFont(font);
// 设置每条折线的颜色
plot.getRenderer().setSeriesPaint(0, Color.BLUE); // 第一个系列:"学校数量"
plot.getRenderer().setSeriesPaint(1, Color.RED);
// 保存为PNG文件
File outputFile = new File("line_chart.png");
try {
ChartUtils.saveChartAsPNG(outputFile ,chart, width ,height);
System.out.println("柱状图已保存至: " + outputFile.getAbsolutePath());
} catch (IOException e) {
System.err.println("保存图表时发生错误: " + e.getMessage());
}
}
}
3D图/条形图
package org.example.map;
import java.awt.*;
import java.io.*;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.general.DefaultPieDataset;
/**
* 3D图/条形图
*/
public class PieChart3D {
public static void main( String[ ] args )throws Exception {
DefaultPieDataset dataset = new DefaultPieDataset( );
dataset.setValue( "IPhone 5s" , Double.valueOf(20) );
dataset.setValue( "三星 Grand" , Double.valueOf( 20 ) );
dataset.setValue( "MotoG" , Double.valueOf( 40 ) );
dataset.setValue( "Nokia Lumia" , Double.valueOf( 10 ) );
JFreeChart chart = ChartFactory.createPieChart3D(
null, // 标题由后续设置 "Mobile Sales"
dataset , // data
true , // include legend
true,
false);
// 设置中文字体
Font font = new Font("SimSun", Font.PLAIN, 16); // 使用宋体
// 设置带字体的标题
chart.setTitle(new TextTitle("3D饼状图", font));
// 设置图例字体
chart.getLegend().setItemFont(font);
final PiePlot3D plot = ( PiePlot3D ) chart.getPlot( );
plot.setStartAngle( 270 );
plot.setForegroundAlpha( 0.60f );
plot.setInteriorGap( 0.02 );
plot.setLabelFont(font);
// 设置每个模块的颜色
plot.setSectionPaint("IPhone 5s", new Color(255, 20, 71)); // 红色
plot.setSectionPaint("三星 Grand", new Color(30, 144, 255)); // 道奇蓝
plot.setSectionPaint("MotoG", new Color(50, 205, 50)); // 苹果绿
plot.setSectionPaint("Nokia Lumia", new Color(255, 165, 0)); // 橙色
int width = 640; /* Width of the image */
int height = 480; /* Height of the image */
File pieChart3D = new File( "pie_Chart3D.jpeg" );
ChartUtils.saveChartAsJPEG( pieChart3D , chart , width , height );
}
}
饼状图
package org.example.map;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.chart.ChartUtils;
/**
* 饼状图
*/
public class PieChart_AWT {
public static void main(String[] args) {
// 创建数据集
PieDataset dataset = createDataset();
// 创建图表
JFreeChart chart = createChart(dataset);
// 保存图表为图片文件
String filePath = "pie_chart_output.png";
try {
ChartUtils.saveChartAsPNG(new File(filePath), chart, 800, 600);
System.out.println("图表已保存至: " + new File(filePath).getAbsolutePath());
} catch (IOException e) {
System.err.println("保存图表时发生错误: " + e.getMessage());
}
}
private static PieDataset createDataset() {
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("IPhone 5s", 15.0);
dataset.setValue("SamSung Grand", 20.0);
dataset.setValue("MotoG", 40.0);
dataset.setValue("Nokia Lumia", 10.0);
return dataset;
}
private static JFreeChart createChart(PieDataset dataset) {
JFreeChart chart = ChartFactory.createPieChart(
null, // 标题由后续设置
dataset, // 数据集
true, // 显示图例
true,
false);
PiePlot plot = (PiePlot) chart.getPlot();
// 设置中文字体
Font font = new Font("SimSun", Font.PLAIN, 12); // 使用宋体
// 设置带字体的标题
chart.setTitle(new TextTitle("手机种类", font));
plot.setLabelFont(font);
plot.setNoDataMessage("无数据");
// 设置标签显示格式:{0} 分类名称,{1} 数值,{2} 百分比
plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}: {1} (占 {2})"));
// plot.setLabelBackgroundPaint(null); // 可选:去掉标签背景色
// 设置图例字体以支持中文
chart.getLegend().setItemFont(font);
// 设置每个模块的颜色
plot.setSectionPaint("IPhone 5s", new Color(255, 20, 71)); // 红色
plot.setSectionPaint("SamSung Grand", new Color(30, 144, 255)); // 道奇蓝
plot.setSectionPaint("MotoG", new Color(50, 205, 50)); // 苹果绿
plot.setSectionPaint("Nokia Lumia", new Color(255, 165, 0)); // 橙色
return chart;
}
}
时间序列图
package org.example.map;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.general.SeriesException;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import java.awt.*;
import java.io.File;
import java.io.IOException;
/**
* 时间序列图
*/
public class TimeSeries_AWT {
public static void main(String[] args) {
// 创建数据集
final TimeSeries series = new TimeSeries( "Random Data" );
Second current = new Second( );
double value = 100.0;
for (int i = 0; i < 4000; i++) {
try {
value = value + Math.random( ) - 0.5;
series.add(current, Double.valueOf(value));
current = ( Second ) current.next( );
} catch ( SeriesException e ) {
System.err.println("Error adding to series");
}
}
TimeSeriesCollection timeSeriesCollection = new TimeSeriesCollection(series);
JFreeChart chart = ChartFactory.createTimeSeriesChart(
null,
"时间(秒)",
"值",
timeSeriesCollection,
false,
false,
false);
XYPlot plot = (XYPlot)chart.getPlot( );
plot.setForegroundAlpha( 0.65F );
XYItemRenderer xyitemrenderer = plot.getRenderer( );
//设置颜色
xyitemrenderer.setSeriesPaint( 0 , Color.blue );
xyitemrenderer.setSeriesPaint( 1 , Color.RED );
// 设置图片尺寸
int width = 560;
int height = 367;
// 设置中文字体
Font font = new Font("SimSun", Font.PLAIN, 16); // 使用宋体
// 设置带字体的标题
chart.setTitle(new TextTitle("时间序列图", font));
// 设置坐标轴标签字体
plot.getDomainAxis().setLabelFont(font);
plot.getRangeAxis().setLabelFont(font);
// 设置坐标轴刻度字体
plot.getDomainAxis().setTickLabelFont(font);
plot.getRangeAxis().setTickLabelFont(font);
// 保存为PNG文件
File outputFile = new File("Time Series.png");
try {
ChartUtils.saveChartAsPNG(outputFile ,chart, width ,height);
System.out.println("时间序列图已保存至: " + outputFile.getAbsolutePath());
} catch (IOException e) {
System.err.println("保存图表时发生错误: " + e.getMessage());
}
}
}
XY图
package org.example.map;
import java.awt.*;
import java.io.*;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.xy.XYSeries;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.xy.XYSeriesCollection;
/**
* XY图
*/
public class XYLineChart_image {
public static void main( String[ ] args )throws Exception {
final XYSeries firefox = new XYSeries( "火狐" );
firefox.add( 1.0 , 1.0 );
firefox.add( 2.0 , 4.0 );
firefox.add( 3.0 , 3.0 );
final XYSeries chrome = new XYSeries( "Chrome" );
chrome.add( 1.0 , 4.0 );
chrome.add( 2.0 , 5.0 );
chrome.add( 3.0 , 6.0 );
final XYSeries iexplorer = new XYSeries( "InternetExplorer" );
iexplorer.add( 3.0 , 4.0 );
iexplorer.add( 4.0 , 5.0 );
iexplorer.add( 5.0 , 4.0 );
final XYSeriesCollection dataset = new XYSeriesCollection( );
dataset.addSeries( firefox );
dataset.addSeries( chrome );
dataset.addSeries( iexplorer );
JFreeChart xylineChart = ChartFactory.createXYLineChart(
null, // 标题由后续设置 "Browser usage statastics",
"种类",
"分数",
dataset,
PlotOrientation.VERTICAL,
true, true, false);
int width = 640; /* Width of the image */
int height = 480; /* Height of the image */
// 设置中文字体
Font font = new Font("SimSun", Font.PLAIN, 16); // 使用宋体
// 设置带字体的标题
xylineChart.setTitle(new TextTitle("XY折线图", font));
// 设置图例字体
xylineChart.getLegend().setItemFont(font);
// 设置坐标轴标签字体
XYPlot plot = xylineChart.getXYPlot();
plot.getDomainAxis().setLabelFont(font);
plot.getRangeAxis().setLabelFont(font);
// 设置坐标轴刻度字体
plot.getDomainAxis().setTickLabelFont(font);
plot.getRangeAxis().setTickLabelFont(font);
// 设置每条折线的颜色
plot.getRenderer().setSeriesPaint(0, Color.BLUE); // 第一个系列:"学校数量"
plot.getRenderer().setSeriesPaint(1, Color.RED);
File XYChart = new File( "XYLineChart.jpeg" );
ChartUtils.saveChartAsJPEG( XYChart, xylineChart, width, height);
}
}