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教程。