終於寫到最後一篇了,最後來看看JFreeChart吧。
JFreeChart是一個開源的Java圖表涵式庫,能夠生成各種類型的圖表,圖表的格式可為JPEG、PNG、SVG等等。在JasperReports中,chart元素也是利用JFreeChart來建立圖表。
就以上一篇Apache POI-圖表(直條圖)建立的圖表為例(如下圖),用JFreeChart來生成一個相似的圖表作為範例。
建立Dataset: 使用CategoryDataset的實作類別DefaultCategoryDataset來建立Dataset,也能實作其他類別繪製更複雜的圖表。以addValue()
方法設定值,三個參數分別為value、rowKey、columnKey,value為Y軸的值,rowKey與columnKey則見下面的說明。
設定圖表主題(選擇性): 可以選擇要不要設定主題,但是如果沒有設定字體而造成圖表文字不會顯示的話,就還是要設定一下。
建立圖表: ChartFactory中有多種方法可以建立不同類型的圖表,如果是BarChart還可以用PlotOrientation.VERTICAL、PlotOrientation.HORIZONTAL,設定bar的方向水平還是垂直的。
設定XY軸(選擇性): 如果想調整軸的刻度、範圍、標籤的顯示,可以利用getRangeAxis()
取得Y軸物件、getDomainAxis()
取得X軸物件,再進行更多設定。
設定圖利(選擇性): 想顯示圖例的話,以getLegend()
取得圖例物件,圖例位置、邊框粗細、字體都是可以設定的。
設定Bar(選擇性): 如果覺得預設的樣式太陽春,直條圖的Bar顏色、寬度,都可以修改。
匯出圖表: 範例中是直接匯出圖檔,可以使用ChartUtils,輕鬆的匯出PNG或JPEG的格式,如果想要匯出SVG則要在Maven加入相關的dependencies。
public void exportBarChart() {
// 1. 建立資料
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(71.304, "課程平均成績", "國文");
dataset.addValue(69.72, "課程平均成績", "數學");
dataset.addValue(69.76, "課程平均成績", "英文");
dataset.addValue(69.488, "課程平均成績", "體育");
// 2. 設定圖表主題
StandardChartTheme standardChartTheme = new StandardChartTheme("myTheme"); // 建立主題
standardChartTheme.setExtraLargeFont(new Font("微軟正黑體", Font.BOLD, 26)); // 標題字體
standardChartTheme.setRegularFont(new Font("微軟正黑體", Font.BOLD, 14)); // 圖例字體
standardChartTheme.setLargeFont(new Font("微軟正黑體", Font.BOLD, 18)); // 座標軸字體
// standardChartTheme.setChartBackgroundPaint(Color.white); // 主題背景顏色
ChartFactory.setChartTheme(standardChartTheme);
// 3. 建立圖表
JFreeChart chart = ChartFactory.createBarChart(
"學生課程平均成績", // 圖表標題
"課程", // 橫坐標標題
"平均成績", // 縱座標標題
dataset, // 資料
PlotOrientation.VERTICAL, // 圖表的繪製方向,表示柱狀圖是垂直的
true, // 是否顯示圖例
true, // 是否啟用工具提示
false // 是否為圖表中的每個數據點生成對應的 URL(互動式圖表時使用)
);
CategoryPlot plot = (CategoryPlot)chart.getPlot(); // 取得圖表物件
plot.setOutlineVisible(false);// 是否顯示邊框
plot.setBackgroundPaint(Color.WHITE);// 背景顏色
plot.setNoDataMessage("無資料");// 無資料時的提示
plot.setNoDataMessageFont(new Font("微軟正黑體", Font.BOLD, 32));// 提示字體
plot.setNoDataMessagePaint(Color.RED);// 提示字顏色
plot.setRangeGridlinesVisible(false);// 是否顯示網格線 橫線
// 4. 軸的設定
// 調整 Y 軸刻度
NumberAxis numberAxis = (NumberAxis) plot.getRangeAxis();
numberAxis.setTickUnit(new NumberTickUnit(5)); // 設定刻度單位為 10
numberAxis.setRange(50, 90); // 設定 Y 軸範圍
// 調整 X 軸顯示
CategoryAxis xAxis = plot.getDomainAxis();
xAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); // 課程名稱傾斜 45 度顯示
xAxis.setTickLabelFont(new Font("微軟正黑體", Font.BOLD, 14)); // 設定課程名稱字體大小
// 5. 圖例
LegendTitle legend = chart.getLegend();// 取得圖例物件
legend.setPosition(RectangleEdge.RIGHT); // 圖例位置
legend.setVisible(true);// 是否顯示圖例
legend.setBorder(0, 0, 0, 0); // 圖例邊框粗细
legend.setItemFont(new Font("微軟正黑體", Font.BOLD, 14)); // 圖例字體大小
// 6. 設置 bar
BarRenderer renderer = (BarRenderer) plot.getRenderer();
// 設定顏色
renderer.setSeriesPaint(0, new Color(156, 114, 243, 255));
// 設定標準的 bar 繪製方式,移除光影效果
renderer.setBarPainter(new StandardBarPainter());
// 設定 bar 的寬度為圖表寬度的 10%
renderer.setMaximumBarWidth(0.1);
// 7. 匯出圖表
try {
String resourcePath = "C:/Users/Desktop/報表範例/JFreeChart";
// 保存到本地(PNG或者JPEG格式)
File file = new File(resourcePath + File.separator +"學生課程平均成績直條圖.jpg");
ChartUtils.saveChartAsPNG(file, chart, 800, 400);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
由於做了各種設定,圖表可以設定的和Excel的直條圖非常接近。
但如果想讓Bar的顏色都不一樣,我目前無法調整出來,因為這個範例的資料不需要複雜的分類。第6步驟設定顏色的renderer.setSeriesPaint()
是以addValue()
的rowKey參數來區分Series,我的rowKey都是"課程平均成績",導致JFreeChart將所有資料視為同一類別。如果將rowKey都改為課程名稱(如下),JFreeChart會認為是各課程(ColumnKey)中的其中一類(rowKey)資料,匯出的圖表Bar會留下其他類資料的空位(實際上沒有其他類的資料)。
// 1. 建立資料
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(71.304, "國文", "國文");
dataset.addValue(69.72, "數學", "數學");
dataset.addValue(69.76, "英文", "英文");
dataset.addValue(69.488, "體育", "體育");
.
.
.
// 6. 設置 bar
BarRenderer renderer = (BarRenderer) plot.getRenderer();
// 設定顏色
renderer.setSeriesPaint(0, new Color(156, 114, 243, 255));
renderer.setSeriesPaint(1, new Color(87, 165, 232));
renderer.setSeriesPaint(2, new Color(170, 232, 149));
renderer.setSeriesPaint(3, new Color(222, 185, 144));
匯出的圖表Bar會偏移,留下其他類資料的空位:
不知道這個部分可以怎麼調整,如果有使用過JFreeChart的前輩看到這篇,希望能再為大家解答~
總之,JFreeChart看起來至少能將圖表做到與Apache POI類似的細節設定,只是設定相對比較複雜,而且匯出的是圖片檔,比較適合用在匯出PDF的功能上。
這次是第一次參賽,感謝開賽前兩週好朋友邀我和大家一起組隊,趁這個機會給自己一個挑戰。雖然有點臨時,文章大綱在過程中也調整了滿多的,內容沒有規畫得很完善,在開賽前對主題中的JasperReports、Apache POI也只用過基本的功能,JFreeChart根本沒用過,但為了把文章寫好,讓自己花時間對主題中的涵式庫進行更深入的了解,真的是收穫滿滿。
我想我的主題算是比較冷門,我想找的部分資料連英文的資源都很少,但身邊仍有同事或朋友在使用,因此趁這個機會將自己的學習經驗留下來,希望有需要做報表的人能看得懂,如果有寫錯或寫不好的地方可以留言告訴我,我會盡量修正讓文章更完善,謝謝各位的閱讀。