iT邦幫忙

2024 iThome 鐵人賽

DAY 30
0
Software Development

Java工程師的報表入門與實作系列 第 30

JFreeChart(直條圖)與完賽心得

  • 分享至 

  • xImage
  •  

終於寫到最後一篇了,最後來看看JFreeChart吧。

JFreeChart

簡介

JFreeChart是一個開源的Java圖表涵式庫,能夠生成各種類型的圖表,圖表的格式可為JPEG、PNG、SVG等等。在JasperReports中,chart元素也是利用JFreeChart來建立圖表。

生成圖表-直條圖

就以上一篇Apache POI-圖表(直條圖)建立的圖表為例(如下圖),用JFreeChart來生成一個相似的圖表作為範例。

建立圖表的步驟

  1. 建立Dataset: 使用CategoryDataset的實作類別DefaultCategoryDataset來建立Dataset,也能實作其他類別繪製更複雜的圖表。以addValue()方法設定值,三個參數分別為value、rowKey、columnKey,value為Y軸的值,rowKey與columnKey則見下面的說明。

    • JFreeChart可以建立如下這種直條圖,能再將X軸的資料以columnKey設定不同類別(Category)或時間點,以rowKey能再設定各種Category內的資料為不同類別或系列。在這個範例中因為資料不需要分這麼細,所以rowKey都設為"課程平均成績",主要以columnKey設定不同課程類別
  2. 設定圖表主題(選擇性): 可以選擇要不要設定主題,但是如果沒有設定字體而造成圖表文字不會顯示的話,就還是要設定一下。

  3. 建立圖表: ChartFactory中有多種方法可以建立不同類型的圖表,如果是BarChart還可以用PlotOrientation.VERTICAL、PlotOrientation.HORIZONTAL,設定bar的方向水平還是垂直的。

  4. 設定XY軸(選擇性): 如果想調整軸的刻度、範圍、標籤的顯示,可以利用getRangeAxis()取得Y軸物件、getDomainAxis()取得X軸物件,再進行更多設定。

  5. 設定圖利(選擇性): 想顯示圖例的話,以getLegend()取得圖例物件,圖例位置、邊框粗細、字體都是可以設定的。

  6. 設定Bar(選擇性): 如果覺得預設的樣式太陽春,直條圖的Bar顏色、寬度,都可以修改。

  7. 匯出圖表: 範例中是直接匯出圖檔,可以使用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根本沒用過,但為了把文章寫好,讓自己花時間對主題中的涵式庫進行更深入的了解,真的是收穫滿滿。
我想我的主題算是比較冷門,我想找的部分資料連英文的資源都很少,但身邊仍有同事或朋友在使用,因此趁這個機會將自己的學習經驗留下來,希望有需要做報表的人能看得懂,如果有寫錯或寫不好的地方可以留言告訴我,我會盡量修正讓文章更完善,謝謝各位的閱讀。


Reference


上一篇
Apache POI-圖表(直條圖)
系列文
Java工程師的報表入門與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言