ChartFactory (工廠)
↓ createXxxChart()
JFreeChart (圖表容器)
├─ Title (標題)
├─ Legend (圖例)
└─ Plot (繪圖區) → CategoryPlot / XYPlot / PiePlot
├─ Domain Axis (域軸/橫軸)
├─ Range Axis (范圍軸/縱軸)
└─ Renderer (渲染器) → LineAndShapeRenderer / BarRenderer ...
public class ChartDemo {
public static void main(String[] args) {
ChartDemo demo = new ChartDemo();
JFreeChart chart = demo.createLineChart();
demo.saveAsFile(chart, "C:/temp/LineChart.jpg"); // 本地文件
// String fileName = demo.saveAsTemp(chart, request.getSession(), response.getWriter()); // Web 臨時文件
}
/** 創建雙序列折線圖 */
public JFreeChart createLineChart() {
// 1. 數據集
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
String s1 = "東京", s2 = "紐約";
String[] types = {"1月","2月","3月","4月","5月","6月","7月"};
double[][] data = {
{1.0, 4.0, 3.0, 5.0, 5.0, 7.0, 7.0}, // 東京
{5.0, 7.0, 6.0, 8.0, 4.0, 4.0, 2.0} // 紐約
};
for (int i = 0; i < types.length; i++) {
dataset.addValue(data[0][i], s1, types[i]);
dataset.addValue(data[1][i], s2, types[i]);
}
// 2. 工廠創建
JFreeChart chart = ChartFactory.createLineChart(
"月均溫度對比", "月份", "溫度 (°C)", dataset,
PlotOrientation.VERTICAL, true, true, false
);
// 3. 圖表級美化
chart.setBackgroundPaint(Color.WHITE);
chart.getLegend().setPosition(RectangleEdge.RIGHT);
chart.getTitle().setFont(new Font("微軟雅黑", Font.BOLD, 16));
chart.getLegend().setItemFont(new Font("微軟雅黑", Font.PLAIN, 12));
// 4. Plot 級美化
CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(Color.LIGHT_GRAY);
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.WHITE);
plot.setRangeGridlinePaint(Color.WHITE);
plot.setAxisOffset(new RectangleInsets(0, 0, 0, 10)); // 與軸留白
// 5. 域軸 (橫軸)
CategoryAxis domain = plot.getDomainAxis();
domain.setCategoryLabelPositions(CategoryLabelPositions.UP_45); // 45° 傾斜
domain.setTickLabelFont(new Font("微軟雅黑", Font.PLAIN, 11));
domain.setLabelFont(new Font("微軟雅黑", Font.BOLD, 13));
// 6. 范圍軸 (縱軸)
NumberAxis range = (NumberAxis) plot.getRangeAxis();
range.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
range.setAutoRangeIncludesZero(true);
range.setTickLabelFont(new Font("微軟雅黑", Font.PLAIN, 11));
range.setLabelFont(new Font("微軟雅黑", Font.BOLD, 13));
range.setUpperBound(10); // 根據數據調整
// 7. 渲染器 (線條/形狀/標籤)
LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
renderer.setShapesVisible(true); // 顯示數據點
renderer.setSeriesStroke(0, new BasicStroke(2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1f, new float[]{10f, 6f}, 0f)); // 虛線
renderer.setSeriesStroke(1, new BasicStroke(2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1f, new float[]{6f, 6f}, 0f));
renderer.setBaseItemLabelsVisible(true);
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
renderer.setBaseItemLabelFont(new Font("微軟雅黑", Font.PLAIN, 10));
return chart;
}
/** 保存為本地圖片文件 */
public void saveAsFile(JFreeChart chart, String path) {
try {
ChartUtilities.saveChartAsJPEG(new File(path), chart, 800, 600);
// 或 saveChartAsPNG
} catch (IOException e) { throw new RuntimeException(e); }
}
/** Web 環境保存為 Session 臨時文件,返回文件名供 DisplayChart Servlet 使用 */
public String saveAsTemp(JFreeChart chart, HttpSession session, PrintWriter out) {
try {
ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
String fileName = ServletUtilities.saveChartAsPNG(chart, 700, 450, info, session);
ChartUtilities.writeImageMap(out, fileName, info, false); // 可選:圖片映射 (熱區)
out.flush();
return fileName;
} catch (IOException e) { throw new RuntimeException(e); }
}
}
<%@ page import="com.demo.ChartDemo" %>
<%
ChartDemo demo = new ChartDemo();
JFreeChart chart = demo.createLineChart();
String fileName = demo.saveAsTemp(chart, session, new PrintWriter(out));
String graphUrl = request.getContextPath() + "/DisplayChart?filename=" + fileName;
%>
<img src="<%= graphUrl %>" width="700" height="450" border="0" usemap="<%= fileName %>" />
| 需求 | API | 備註 |
|---|---|---|
| 設置標題字體 | chart.getTitle().setFont(Font) | |
| 圖例位置 | chart.getLegend().setPosition(RectangleEdge) | TOP/BOTTOM/LEFT/RIGHT |
| 背景色 | chart.setBackgroundPaint(Paint) / plot.setBackgroundPaint(Paint) | |
| 網格線顏色/可見 | plot.setDomainGridlinePaint(Color) / setDomainGridlinesVisible(boolean) | |
| 坐標軸標籤字體 | axis.setTickLabelFont(Font) / axis.setLabelFont(Font) | |
| 坐標軸傾斜 | domain.setCategoryLabelPositions(CategoryLabelPositions.UP_45) | DOWN_45, UP_90 等 |
| 縱軸整數刻度 | range.setStandardTickUnits(NumberAxis.createIntegerTickUnits()) | |
| 數據點可見 | renderer.setShapesVisible(true) | |
| 線條虛線 | renderer.setSeriesStroke(index, BasicStroke) | float[] {on, off, ...} |
| 數值標籤 | renderer.setBaseItemLabelsVisible(true) + setBaseItemLabelGenerator(...) | |
| 導出高清圖 | ChartUtilities.saveChartAsPNG/JPEG(File, chart, w, h) | |
| Web 臨時文件 | ServletUtilities.saveChartAsPNG(chart, w, h, info, session) | 需 web.xml 配置 DisplayChart |
所有 setFont 統一指定支持中文的字體(微軟雅黑、SimHei、Noto Sans CJK SC)。
Linux 服務器必須安裝字體包:yum install google-noto-sans-cjk-ttc-fonts 或 apt install fonts-noto-cjk。