JFreeChart 以工廠模式 (ChartFactory) 統一建立圖表,核心差異在於 Dataset 類型。本文提供三種最常用圖表的完整可運行代碼:餅圖 (DefaultPieDataset)、時間序列折線圖 (TimeSeriesCollection)、垂直柱狀圖 (DefaultCategoryDataset),涵蓋資料構建、圖表創建、標題/字體/背景/刻度/透明度美化、JPEG/PNG 輸出全流程。
import org.jfree.chart.*;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.plot.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.time.*;
import org.jfree.chart.ChartUtilities;
import java.awt.*;
import java.io.File;
注意:舊版 (0.9.x) 套件為 com.jrefinery.*,新版統一為 org.jfree.*。
public void createPieChart() {
// 1. 資料集
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("聯想", 27.3);
dataset.setValue("長城", 12.2);
dataset.setValue("海爾", 5.5);
dataset.setValue("美的", 17.1);
dataset.setValue("松下", 9.0);
dataset.setValue("科龍", 19.0);
// 2. 建立圖表
JFreeChart chart = ChartFactory.createPieChart(
"2023 年空調市場佔有率", dataset, true, true, false);
// 3. 美化
chart.setTitle(new TextTitle("2023 年空調市場佔有率", new Font("微軟正黑體", Font.BOLD, 18)));
chart.setBackgroundPaint(Color.WHITE);
PiePlot plot = (PiePlot) chart.getPlot();
plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}: {1} ({2})", NumberFormat.getNumberInstance(), NumberFormat.getPercentInstance()));
plot.setSectionPaint("聯想", new Color(0x4472C4));
plot.setSectionPaint("海爾", new Color(0xED7D31));
plot.setBackgroundPaint(Color.WHITE);
plot.setOutlineVisible(false);
plot.setLabelFont(new Font("微軟正黑體", Font.PLAIN, 12));
plot.setLabelGap(0.02);
// 4. 輸出
saveChart(chart, "pie_market_share.jpg");
}
public void createTimeSeriesChart() {
// 1. 時間序列資料集
TimeSeriesCollection dataset = new TimeSeriesCollection();
TimeSeries ufida = new TimeSeries("用友");
TimeSeries kingdee = new TimeSeries("金碟");
TimeSeries neusoft = new TimeSeries("東軟");
// 模擬 1999-2004 年每月資料
for (int y = 1999; y < 2005; y++) {
for (int m = 1; m <= 12; m++) {
Day day = new Day(1, m, y);
ufida.add(new TimeSeriesDataItem(day, 500 + Math.random() * 100));
kingdee.add(new TimeSeriesDataItem(day, 400 - Math.random() * 100));
neusoft.add(new TimeSeriesDataItem(day, 300 - Math.random() * 100));
}
}
dataset.addSeries(ufida);
dataset.addSeries(kingdee);
dataset.addSeries(neusoft);
// 2. 建立圖表
JFreeChart chart = ChartFactory.createTimeSeriesChart(
"ERP 廠商應收帳款趨勢", "月份", "應收餘額", dataset, true, true, false);
// 3. 美化
chart.setTitle(new TextTitle("ERP 廠商應收帳款趨勢", new Font("微軟正黑體", Font.BOLD, 18)));
chart.addSubtitle(new TextTitle("1999-2004 財年分析", new Font("微軟正黑體", Font.PLAIN, 14)));
chart.setBackgroundPaint(new GradientPaint(0, 0, Color.WHITE, 0, 1000, new Color(220, 230, 245)));
XYPlot plot = (XYPlot) chart.getPlot();
plot.setBackgroundPaint(Color.WHITE);
plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
plot.getRenderer().setSeriesPaint(0, Color.BLUE);
plot.getRenderer().setSeriesPaint(1, Color.RED);
plot.getRenderer().setSeriesPaint(2, Color.GREEN);
// 4. 輸出
saveChart(chart, "timeseries_ar_trend.jpg");
}
public void createBarChart() {
// 1. 類別資料集
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
String[] units = {"單位一", "單位二", "單位三", "單位四", "單位五"};
String[] months = {"1月", "2月", "3月", "4月", "5月", "6月"};
for (int r = 0; r < units.length; r++) {
for (int c = 0; c < months.length; c++) {
dataset.addValue(r * c + 5 + Math.random() * 10, units[r], months[c]);
}
}
// 2. 建立圖表
JFreeChart chart = ChartFactory.createBarChart(
"各單位半年績效比較", "單位", "績效分數", dataset,
PlotOrientation.VERTICAL, true, true, false);
// 3. 美化
chart.setTitle(new TextTitle("各單位半年績效比較", new Font("微軟正黑體", Font.BOLD, 18)));
chart.setBackgroundPaint(new GradientPaint(0, 0, Color.WHITE, 1000, 0, new Color(255, 235, 235)));
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setBackgroundPaint(Color.WHITE);
plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
plot.getRenderer().setSeriesPaint(0, new Color(0x4472C4));
// Y軸強制整數刻度
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
// 4. 輸出
saveChart(chart, "bar_performance.jpg");
}
private void saveChart(JFreeChart chart, String fileName) {
File dir = new File("output");
if (!dir.exists()) dir.mkdirs();
File file = new File(dir, fileName);
try {
// 品質 1.0 (無損), 寬 800, 高 600
ChartUtilities.saveChartAsJPEG(file, 1.0f, chart, 800, 600);
// 或 PNG: ChartUtilities.saveChartAsPNG(file, chart, 800, 600);
System.out.println("圖表已儲存: " + file.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
}
import org.jfree.chart.StandardChartTheme;
StandardChartTheme theme = new StandardChartTheme("CN");
theme.setExtraLargeFont(new Font("微軟正黑體", Font.BOLD, 20)); // 標題
theme.setLargeFont(new Font("微軟正黑體", Font.PLAIN, 14)); // 軸標籤
theme.setRegularFont(new Font("微軟正黑體", Font.PLAIN, 12)); // 圖例、提示
theme.setSmallFont(new Font("微軟正黑體", Font.PLAIN, 10)); // 刻度
ChartFactory.setChartTheme(theme);
| 圖表 | Dataset | Factory Method | 適用場景 |
|---|---|---|---|
| 餅圖 | PieDataset | createPieChart | 佔比、構成分析 |
| 環狀圖 | PieDataset | createRingChart | 佔比 (中空可放總計) |
| 折線圖 (時間) | TimeSeriesCollection | createTimeSeriesChart | 趨勢、時間序列 |
| 折線圖 (XY) | XYDataset | createXYLineChart | 科學函數、相關性 |
| 柱狀圖 | CategoryDataset | createBarChart | 分群比較、排名 |
| 堆疊柱狀 | CategoryDataset | createStackedBarChart | 部分與整體關係 |
| 散佈圖 | XYDataset | createScatterPlot | 分布、聚類 |
| 甘特圖 | TaskSeriesCollection | createGanttChart | 專案排程 |
| 燭台圖 | OHLCDataset | createCandlestickChart | 股票 K 線 |