JFreeChart
最后修改于 2024 年 1 月 27 日
在本文中,我们将学习如何使用 JFreeChart。我们将展示如何创建各种类型的图表。图表显示在 Swing 应用程序中,并保存到图像文件中。我们使用 Java servlet 在 Web 浏览器中创建和呈现图表,并从 MySQL 数据库检索图表数据。
JFreeChart 库
图表是一种以简单方式显示信息的图形,通常使用线条和曲线来显示数量。JFreeChart 是一个流行的 Java 图表创建库。 JFreeChart 允许创建各种交互式和非交互式图表。我们可以创建折线图、柱状图、面积图、散点图、饼图、甘特图以及各种专用图表,例如风向图或气泡图。
JFreeChart 具有广泛的可定制性;它允许修改图表项目、图例、线条或标记的颜色和样式。它可以自动绘制坐标轴刻度和图例。图表具有内置的鼠标缩放功能。现有的图表可以通过库在数据集合上拥有的监听器轻松更新。它支持多种输出格式,包括 PNG、JPEG、PDF 和 SVG。
JFreeChart 由 David Gilbert 于 2000 年启动。如今,JFreeChart 是 Java 开发人员中使用最广泛的图表库。
JFreeChart Maven 依赖
<dependency> <groupId>org.jfree</groupId> <artifactId>jfreechart</artifactId> <version>1.5.3</version> </dependency>
对于我们的项目,我们使用这个 Maven 依赖。
JFreeChart 直方图
直方图是数值数据分布的准确表示。它是连续变量的概率分布的估计。
package com.zetcode; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; import org.jfree.data.statistics.HistogramDataset; import java.io.File; import java.io.IOException; public class HistogramEx { public static void main(String[] args) throws IOException { double[] vals = { 0.71477137, 0.55749811, 0.50809619, 0.47027228, 0.25281568, 0.66633175, 0.50676332, 0.6007552, 0.56892904, 0.49553407, 0.61093935, 0.65057417, 0.40095626, 0.45969447, 0.51087888, 0.52894806, 0.49397198, 0.4267163, 0.54091298, 0.34545257, 0.58548892, 0.3137885, 0.63521146, 0.57541744, 0.59862265, 0.66261386, 0.56744017, 0.42548488, 0.40841345, 0.47393027, 0.60882106, 0.45961208, 0.43371424, 0.40876484, 0.64367337, 0.54092033, 0.34240811, 0.44048106, 0.48874236, 0.68300902, 0.33563968, 0.58328107, 0.58054283, 0.64710522, 0.37801285, 0.36748982, 0.44386445, 0.47245989, 0.297599, 0.50295541, 0.39785732, 0.51370486, 0.46650358, 0.5623638, 0.4446957, 0.52949791, 0.54611411, 0.41020067, 0.61644868, 0.47493691, 0.50611458, 0.42518211, 0.45467712, 0.52438467, 0.724529, 0.59749142, 0.45940223, 0.53099928, 0.65159718, 0.38038268, 0.51639554, 0.41847437, 0.46022878, 0.57326103, 0.44913632, 0.61043611, 0.42694949, 0.43997814, 0.58787928, 0.36252603, 0.50937634, 0.47444256, 0.57992527, 0.29381335, 0.50357977, 0.42469464, 0.53049697, 0.7163579, 0.39741694, 0.41980533, 0.68091159, 0.69330702, 0.50518926, 0.55884098, 0.48618324, 0.48469854, 0.55342267, 0.67159111, 0.62352006, 0.34773486}; var dataset = new HistogramDataset(); dataset.addSeries("key", vals, 50); JFreeChart histogram = ChartFactory.createHistogram("Normal distribution", "y values", "x values", dataset); ChartUtils.saveChartAsPNG(new File("histogram.png"), histogram, 450, 400); } }
在此示例中,我们为值的随机分布生成直方图。该图表生成为 PNG 文件并保存在磁盘上。
var dataset = new HistogramDataset(); dataset.addSeries("key", vals, 50);
直方图在 HistogramDataset
中显示值。 addSeries
方法的第二个参数是双精度值数组。第三个是 bin 的数量,即图表上绘制的矩形的数量。
JFreeChart histogram = ChartFactory.createHistogram("Normal distribution", "y values", "x values", dataset);
直方图使用 ChartFactory.createHistogram
方法创建。
ChartUtils.saveChartAsPNG(new File("histogram.png"), histogram, 450, 400);
我们使用 ChartUtils.saveChartAsPNG
将图表写入 PNG 图像。
JFreeChart 折线图
折线图是一种基本的图表类型,它将信息显示为一系列由直线段连接的数据点。 JavaFX 中的折线图使用 ChartFactory.createXYLineChart
创建。
package com.zetcode; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.block.BlockBorder; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.title.TextTitle; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import javax.swing.BorderFactory; import javax.swing.JFrame; import java.awt.BasicStroke; import java.awt.Color; import java.awt.EventQueue; import java.awt.Font; public class LineChartEx extends JFrame { public LineChartEx() { initUI(); } private void initUI() { XYDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); chartPanel.setBackground(Color.white); add(chartPanel); pack(); setTitle("Line chart"); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private XYDataset createDataset() { var series = new XYSeries("2016"); series.add(18, 567); series.add(20, 612); series.add(25, 800); series.add(30, 980); series.add(40, 1410); series.add(50, 2350); var dataset = new XYSeriesCollection(); dataset.addSeries(series); return dataset; } private JFreeChart createChart(XYDataset dataset) { JFreeChart chart = ChartFactory.createXYLineChart( "Average salary per age", "Age", "Salary (€)", dataset, PlotOrientation.VERTICAL, true, true, false ); XYPlot plot = chart.getXYPlot(); var renderer = new XYLineAndShapeRenderer(); renderer.setSeriesPaint(0, Color.RED); renderer.setSeriesStroke(0, new BasicStroke(2.0f)); plot.setRenderer(renderer); plot.setBackgroundPaint(Color.white); plot.setRangeGridlinesVisible(true); plot.setRangeGridlinePaint(Color.BLACK); plot.setDomainGridlinesVisible(true); plot.setDomainGridlinePaint(Color.BLACK); chart.getLegend().setFrame(BlockBorder.NONE); chart.setTitle(new TextTitle("Average Salary per Age", new Font("Serif", java.awt.Font.BOLD, 18) ) ); return chart; } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new LineChartEx(); ex.setVisible(true); }); } }
在此示例中,我们创建一个折线图,显示每个年龄段的平均工资。
var series = new XYSeries("2016"); series.add(18, 567); series.add(20, 612); series.add(25, 800); ...
XYSeries
表示 (x, y) 形式的零个或多个数据项序列。
var dataset = new XYSeriesCollection(); dataset.addSeries(series);
该序列被添加到 XYSeriesCollection
,它是可用作数据集的 XYSeries
对象的集合。
JFreeChart chart = ChartFactory.createXYLineChart( "Average salary per age", "Age", "Salary (€)", dataset, PlotOrientation.VERTICAL, true, true, false );
ChartFactory.createXYLineChart
创建一个新的折线图。该方法的参数为:图表标题、X 轴标签、Y 轴标签、数据、绘图方向以及三个标志,指示是否显示图例、工具提示和 URL。
XYPlot plot = chart.getXYPlot();
我们获取对绘图的引用以便对其进行自定义。
var renderer = new XYLineAndShapeRenderer(); renderer.setSeriesPaint(0, Color.RED); renderer.setSeriesStroke(0, new BasicStroke(2.0f)); plot.setRenderer(renderer);
在这里,我们为图表的线条设置笔触和颜色。 XYLineAndShapeRenderer
是一个用线条连接数据点和/或在每个数据点绘制形状的对象。渲染器使用 setRenderer
方法设置。
plot.setBackgroundPaint(Color.white);
setBackgroundPaint
设置绘图区域的背景颜色。
plot.setRangeGridlinesVisible(true); plot.setRangeGridlinePaint(Color.BLACK); plot.setDomainGridlinesVisible(true); plot.setDomainGridlinePaint(Color.BLACK);
我们显示网格线并以黑色绘制。
chart.getLegend().setFrame(BlockBorder.NONE);
我们删除图例周围的边框。
chart.setTitle(new TextTitle("Average Salary per Age", new Font("Serif", java.awt.Font.BOLD, 18) ) );
我们使用新字体创建图表标题。

具有两个序列的折线图
在第二个示例中,我们创建一个包含两个数据序列的折线图。
package com.zetcode; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.block.BlockBorder; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.chart.title.TextTitle; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import javax.swing.BorderFactory; import javax.swing.JFrame; import java.awt.BasicStroke; import java.awt.Color; import java.awt.EventQueue; import java.awt.Font; public class LineChartEx2 extends JFrame { public LineChartEx2() { initUI(); } private void initUI() { XYDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); chartPanel.setBackground(Color.white); add(chartPanel); pack(); setTitle("Line chart"); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private XYDataset createDataset() { var series1 = new XYSeries("2014"); series1.add(18, 530); series1.add(20, 580); series1.add(25, 740); series1.add(30, 901); series1.add(40, 1300); series1.add(50, 2219); var series2 = new XYSeries("2016"); series2.add(18, 567); series2.add(20, 612); series2.add(25, 800); series2.add(30, 980); series2.add(40, 1210); series2.add(50, 2350); var dataset = new XYSeriesCollection(); dataset.addSeries(series1); dataset.addSeries(series2); return dataset; } private JFreeChart createChart(final XYDataset dataset) { JFreeChart chart = ChartFactory.createXYLineChart( "Average salary per age", "Age", "Salary (€)", dataset, PlotOrientation.VERTICAL, true, true, false ); XYPlot plot = chart.getXYPlot(); var renderer = new XYLineAndShapeRenderer(); renderer.setSeriesPaint(0, Color.RED); renderer.setSeriesStroke(0, new BasicStroke(2.0f)); renderer.setSeriesPaint(1, Color.BLUE); renderer.setSeriesStroke(1, new BasicStroke(2.0f)); plot.setRenderer(renderer); plot.setBackgroundPaint(Color.white); plot.setRangeGridlinesVisible(false); plot.setDomainGridlinesVisible(false); chart.getLegend().setFrame(BlockBorder.NONE); chart.setTitle(new TextTitle("Average Salary per Age", new Font("Serif", Font.BOLD, 18) ) ); return chart; } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new LineChartEx2(); ex.setVisible(true); }); } }
该示例绘制一个包含两个数据序列的折线图。
var series1 = new XYSeries("2014"); series1.add(18, 530); series1.add(20, 580); series1.add(25, 740); ...
我们创建第一个系列;它包含 2014 年的数据。
var series2 = new XYSeries("2016"); series2.add(18, 567); series2.add(20, 612); series2.add(25, 800); ...
创建第二个数据系列;它包含 2016 年的数据。
var dataset = new XYSeriesCollection(); dataset.addSeries(series1); dataset.addSeries(series2);
这些序列使用 addSeries
方法添加到 XYSeriesCollection
。
renderer.setSeriesPaint(0, Color.RED); renderer.setSeriesStroke(0, new BasicStroke(2.0f)); renderer.setSeriesPaint(1, Color.BLUE); renderer.setSeriesStroke(1, new BasicStroke(2.0f));
一条线以红色绘制,另一条线以蓝色绘制。
plot.setRangeGridlinesVisible(false); plot.setDomainGridlinesVisible(false);
网格线已关闭。

将折线图保存到图像
ChartUtils
是 JFreeChart 的实用程序方法集合。它包括将图表转换为图像格式和创建简单 HTML 图像映射的方法。
package com.zetcode; 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.plot.PlotOrientation; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; public class LineChartToPNGEx { public static void main(String[] args) throws IOException { var series1 = new XYSeries("2014"); series1.add(18, 530); series1.add(20, 580); series1.add(25, 740); series1.add(30, 901); series1.add(40, 1300); series1.add(50, 2219); var dataset = new XYSeriesCollection(); dataset.addSeries(series1); JFreeChart chart = ChartFactory.createXYLineChart( "Average salary per age", "Age", "Salary (€)", dataset, PlotOrientation.VERTICAL, true, true, false ); ChartUtils.saveChartAsPNG(new File("line_chart.png"), chart, 450, 400); } }
该示例创建一个折线图并将其保存到 PNG 文件中。
ChartUtils.saveChartAsPNG(new File("line_chart.png"), chart, 450, 400);
ChartUtils.saveChartAsPNG
将图表以 PNG 格式保存到指定的文件中。
JFreeChart 气泡图
气泡图是具有附加维度的散点图的变体。我们使用气泡而不是数据点。前两个维度可视化为坐标。气泡的大小表示附加维度。
气泡图在 JFreeChart 中使用 ChartFactory.createBubbleChart
方法创建。
package com.zetcode; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; 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.XYBubbleRenderer; import org.jfree.chart.title.TextTitle; import org.jfree.data.xy.DefaultXYZDataset; import org.jfree.data.xy.XYZDataset; import javax.swing.BorderFactory; import javax.swing.JFrame; import java.awt.Color; import java.awt.EventQueue; import java.awt.Font; public class BubbleChartEx extends JFrame { public BubbleChartEx() { initUI(); } private void initUI() { XYZDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); chartPanel.setBackground(Color.white); add(chartPanel); pack(); setTitle("Bubble chart"); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private XYZDataset createDataset() { var dataset = new DefaultXYZDataset(); dataset.addSeries("Product A", new double[][]{{50}, {642}, {23 * 5}}); dataset.addSeries("Product B", new double[][]{{23}, {540}, {47 * 5}}); dataset.addSeries("Product C", new double[][]{{19}, {188}, {30 * 5}}); return dataset; } private JFreeChart createChart(XYZDataset dataset) { JFreeChart chart = ChartFactory.createBubbleChart( "Products", "Quantity", "Price", dataset, PlotOrientation.VERTICAL, true, true, false); XYPlot plot = (XYPlot) chart.getPlot(); NumberAxis nax1 = (NumberAxis) plot.getDomainAxis(); nax1.setLowerMargin(0.2); nax1.setUpperMargin(0.2); NumberAxis nax2 = (NumberAxis) plot.getRangeAxis(); nax2.setLowerMargin(0.9); nax2.setUpperMargin(0.9); XYBubbleRenderer renderer = (XYBubbleRenderer) plot.getRenderer(); renderer.setDefaultItemLabelsVisible(true); chart.setTitle(new TextTitle("Products", new Font("Serif", java.awt.Font.BOLD, 18)) ); return chart; } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new BubbleChartEx(); ex.setVisible(true); }); } }
我们有三种产品。对于这些产品,我们有它们的数量、价格和市场份额。数量放在 x 轴上,价格放在 y 轴上。市场份额值是 z 值;它们由气泡表示。
private XYZDataset createDataset() { var dataset = new DefaultXYZDataset(); dataset.addSeries("Product A", new double[][]{{50}, {642}, {23 * 5}}); dataset.addSeries("Product B", new double[][]{{23}, {540}, {47 * 5}}); dataset.addSeries("Product C", new double[][]{{19}, {188}, {30 * 5}}); return dataset; }
气泡图使用 XYZDataset
。 z 值(市场份额)已调整;我们使圆圈更大。
JFreeChart chart = ChartFactory.createBubbleChart( "Products", "Quantity", "Price", dataset, PlotOrientation.VERTICAL, true, true, false);
我们使用 ChartFactory.createBubbleChart
创建图表。
NumberAxis nax1 = (NumberAxis) plot.getDomainAxis(); nax1.setLowerMargin(0.2); nax1.setUpperMargin(0.2); NumberAxis nax2 = (NumberAxis) plot.getRangeAxis(); nax2.setLowerMargin(0.9); nax2.setUpperMargin(0.9);
我们调整轴上的值,以便所有气泡都可见。
JFreeChart 面积图
面积图以图形方式显示随时间变化的定量数据。面积图在 JFreeChart 中使用 ChartFactory.createAreaChart
方法创建。
package com.zetcode; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.renderer.AreaRendererEndType; import org.jfree.chart.renderer.category.AreaRenderer; import org.jfree.chart.title.TextTitle; import org.jfree.data.category.CategoryDataset; import org.jfree.data.general.DatasetUtils; import javax.swing.BorderFactory; import javax.swing.JFrame; import java.awt.Color; import java.awt.EventQueue; import java.awt.Font; public class AreaChartEx extends JFrame { public AreaChartEx() { initUI(); } private void initUI() { CategoryDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); chartPanel.setBackground(Color.white); add(chartPanel); pack(); setTitle("Area chart"); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private CategoryDataset createDataset() { double[][] data = new double[][]{ {82502, 84026, 85007, 86216, 85559, 84491, 87672, 88575, 89837, 90701} }; CategoryDataset dataset = DatasetUtils.createCategoryDataset( new String[]{"Oil"}, new String[]{"2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013"}, data ); return dataset; } private JFreeChart createChart(CategoryDataset dataset) { JFreeChart chart = ChartFactory.createAreaChart( "Oil consumption", "Time", "Thousands bbl/day", dataset, PlotOrientation.VERTICAL, false, true, true ); CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setForegroundAlpha(0.3f); AreaRenderer renderer = (AreaRenderer) plot.getRenderer(); renderer.setEndType(AreaRendererEndType.LEVEL); chart.setTitle(new TextTitle("Oil consumption", new Font("Serif", java.awt.Font.BOLD, 18)) ); return chart; } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new AreaChartEx(); ex.setVisible(true); }); } }
该示例显示了一个面积图,显示了世界原油按年份的消费量。
double[][] data = new double[][]{ {82502, 84026, 85007, 86216, 85559, 84491, 87672, 88575, 89837, 90701} }; CategoryDataset dataset = DatasetUtils.createCategoryDataset( new String[]{"Oil"}, new String[]{"2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013"}, data );
数据集是使用 DatasetUtils.createCategoryDataset
方法创建的。类别数据集的值与类别关联。在我们的示例中,我们有与石油消费相关的年份。
CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setForegroundAlpha(0.3f);
我们使用 setForegroundAlpha
方法使图表透明。
AreaRenderer renderer = (AreaRenderer) plot.getRenderer(); renderer.setEndType(AreaRendererEndType.LEVEL);
我们调整图表的结尾。

JFreeChart 柱状图
条形图使用矩形条呈现分组数据,条的长度与它们表示的值成比例。 这些条可以垂直或水平绘制。
package com.zetcode; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.CategoryDataset; import org.jfree.data.category.DefaultCategoryDataset; import javax.swing.BorderFactory; import javax.swing.JFrame; import java.awt.Color; import java.awt.EventQueue; public class BarChartEx extends JFrame { public BarChartEx() { initUI(); } private void initUI() { CategoryDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); chartPanel.setBackground(Color.white); add(chartPanel); pack(); setTitle("Bar chart"); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private CategoryDataset createDataset() { var dataset = new DefaultCategoryDataset(); dataset.setValue(46, "Gold medals", "USA"); dataset.setValue(38, "Gold medals", "China"); dataset.setValue(29, "Gold medals", "UK"); dataset.setValue(22, "Gold medals", "Russia"); dataset.setValue(13, "Gold medals", "South Korea"); dataset.setValue(11, "Gold medals", "Germany"); return dataset; } private JFreeChart createChart(CategoryDataset dataset) { JFreeChart barChart = ChartFactory.createBarChart( "Olympic gold medals in London", "", "Gold medals", dataset, PlotOrientation.VERTICAL, false, true, false); return barChart; } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new BarChartEx(); ex.setVisible(true); }); } }
代码示例使用柱状图显示伦敦 2012 年每个国家/地区的奥运金牌数量。
var dataset = new DefaultCategoryDataset(); dataset.setValue(46, "Gold medals", "USA"); dataset.setValue(38, "Gold medals", "China"); dataset.setValue(29, "Gold medals", "UK"); dataset.setValue(22, "Gold medals", "Russia"); dataset.setValue(13, "Gold medals", "South Korea"); dataset.setValue(11, "Gold medals", "Germany");
我们使用 DefaultCategoryDataset
创建数据集。
JFreeChart barChart = ChartFactory.createBarChart( "Olympic gold medals in London", "", "Gold medals", dataset, PlotOrientation.VERTICAL, false, true, false);
柱状图使用 ChartFactory.createBarChart
方法创建。

JFreeChart 饼图
饼图是一个圆形图表,分为多个切片以说明数值比例。饼图在 JFreeChart 中使用 ChartFactory.createPieChart
方法创建。
package com.zetcode; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.data.general.DefaultPieDataset; import javax.swing.BorderFactory; import javax.swing.JFrame; import java.awt.Color; import java.awt.EventQueue; public class PieChartEx extends JFrame { public PieChartEx() { initUI(); } private void initUI() { DefaultPieDataset dataset = createDataset(); JFreeChart chart = createChart(dataset); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); chartPanel.setBackground(Color.white); add(chartPanel); pack(); setTitle("Pie chart"); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private DefaultPieDataset createDataset() { var dataset = new DefaultPieDataset(); dataset.setValue("Apache", 52); dataset.setValue("Nginx", 31); dataset.setValue("IIS", 12); dataset.setValue("LiteSpeed", 2); dataset.setValue("Google server", 1); dataset.setValue("Others", 2); return dataset; } private JFreeChart createChart(DefaultPieDataset dataset) { JFreeChart pieChart = ChartFactory.createPieChart( "Web servers market share", dataset, false, true, false); return pieChart; } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new PieChartEx(); ex.setVisible(true); }); } }
该示例使用饼图显示 Web 服务器的市场份额。
var dataset = new DefaultPieDataset(); dataset.setValue("Apache", 52); dataset.setValue("Nginx", 31); dataset.setValue("IIS", 12); ...
DefaultPieDataset
用于创建数据集。
JFreeChart barChart = ChartFactory.createPieChart( "Web servers market share", dataset, false, true, false);
使用 ChartFactory.createPieChart
方法创建一个新的饼图。
Servlet 中的 JFreeChart
在以下示例中,我们使用 Java servlet 创建饼图。该图表在 Web 浏览器中呈现。
package com.zetcode.web; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; import org.jfree.data.general.DefaultPieDataset; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; @WebServlet(name = "DoChart", urlPatterns = {"/DoChart"}) public class DoChart extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("image/png"); OutputStream outputStream = response.getOutputStream(); JFreeChart chart = getChart(); int width = 500; int height = 350; ChartUtils.writeChartAsPNG(outputStream, chart, width, height); } public JFreeChart getChart() { var dataset = new DefaultPieDataset(); dataset.setValue("Croatia", 22); dataset.setValue("Bohemia", 34); dataset.setValue("Bulgaria", 18); dataset.setValue("Spain", 5); dataset.setValue("Others", 21); JFreeChart chart = ChartFactory.createPieChart("Popular destinations", dataset, true, false, false); chart.setBorderVisible(false); return chart; } }
DoChart
servlet 创建一个饼图并将其发送给客户端。
response.setContentType("image/png");
setContentType
将内容设置为 PNG 图像。
OutputStream outputStream = response.getOutputStream();
通过 getOutputStream
方法,我们获得一个输出流。这是一个我们向其发送数据的通道。
ChartUtils.writeChartAsPNG(outputStream, chart, width, height);
ChartUtils.writeChartAsPNG
将二进制数据写入 outputstrem。

显示来自 MySQL 数据库的数据
JDBCCategoryDataset
是通过数据库 JDBC 结果集实现的 CategoryDataset
。数据集通过调用带有字符串 SQL 查询的 executeQuery
来填充。
DROP TABLE IF EXISTS GoldMedalsLondon; CREATE TABLE GoldMedalsLondon ( Id int(11) NOT NULL AUTO_INCREMENT, Country text, Medals int(11) DEFAULT NULL, PRIMARY KEY (Id) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1; LOCK TABLES GoldMedalsLondon WRITE; INSERT INTO GoldMedalsLondon VALUES (1,'USA',46),(2,'China',38),(3,'UK',29), (4,'Russia',22),(5,'South Korea',13),(6,'Germany',11); UNLOCK TABLES;
我们在 MySQL 数据库表中有此数据。
mysql> SELECT * FROM GoldMedalsLondon; +----+-------------+--------+ | Id | Country | Medals | +----+-------------+--------+ | 1 | USA | 46 | | 2 | China | 38 | | 3 | UK | 29 | | 4 | Russia | 22 | | 5 | South Korea | 13 | | 6 | Germany | 11 | +----+-------------+--------+ 6 rows in set (0.00 sec)
我们使用 mysql
工具显示数据。
package com.zetcode; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.jdbc.JDBCCategoryDataset; import java.io.File; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class MySQLChartEx { private static JDBCCategoryDataset dataset; public static void main(String[] args) throws IOException, SQLException { String url = "jdbc:mysql://:3306/testdb"; String user = "root"; String password = "s$cret"; try (Connection con = DriverManager.getConnection(url, user, password)) { dataset = new JDBCCategoryDataset(con); dataset.executeQuery("SELECT Country, Medals FROM GoldMedalsLondon"); } JFreeChart barChart = ChartFactory.createBarChart( "Olympic Gold medals in London", "", "Gold medals", dataset, PlotOrientation.VERTICAL, false, true, false); ChartUtils.saveChartAsPNG(new File("medals.png"), barChart, 450, 400); } }
该示例从 MySQL 表中检索数据,创建一个柱状图,并将其保存到 PNG 图像中。
try (Connection con = DriverManager.getConnection(url, user, password)) { dataset = new JDBCCategoryDataset(con); dataset.executeQuery("SELECT Country, Medals FROM GoldMedalsLondon"); }
创建 JDBCCategoryDataset
;它将数据库连接作为参数。
dataset.executeQuery("SELECT Country, Medals FROM GoldMedalsLondon");
executeQuery
通过针对现有数据库连接执行提供的查询来填充数据集。 SQL 查询必须至少返回两列。第一列是类别名称,其余列是值。
JFreeChart barChart = ChartFactory.createBarChart( "Olympic Gold medals in London", "", "Gold medals", dataset, PlotOrientation.VERTICAL, false, true, false);
创建柱状图。
ChartUtils.saveChartAsPNG(new File("medals.png"), barChart, 450, 400);\
柱状图使用 ChartUtils.saveChartAsPNG
方法保存到 PNG 文件。
来源
在本文中,我们使用 JFreeChart 在 Java 中创建了一些基本图表。
作者
列出所有Java教程。