2010年9月14日 星期二

[ Java 小學堂 ] 使用 JFreeChart 製作美觀易懂的圖表

前言 : 
再開發應用程式時, 使用者常希望將系統中的資料以多樣化統計圖表呈現. 如此一來應用系統將能因為使用多彩多樣圖表介面的方便易懂. 這裡介紹 JFreeChart 來提供一組免費下載的統計圖表程式庫, 它提供了多種統計圖表, 如 : pie chart, bar char etc... 另外 JFreeChart 也提供很多類別函式讓 Programmer 能客製圖表的樣式效果. 甚至能將圖表 export 成為 PDF 檔案. 
要使用這組程式庫, 請先到下列網址下載 : 
http://sourceforge.net/projects/jfreechart/files/ 

解壓縮後, 找出其中兩個 .jar 檔案 : 
1. jcommon-1.0.16.jar : JCommon class library 
提供 JFreeChart 底層操作所需要的各項類別.

2. jfreechart-1.0.13.jar : 這是 JFreeChart 主要的類別程式庫 : 
- org.jfree.chart : 圖表樣式的介面或類別定義.
- org.jfree.data : 圖表所需的資料結構, 資料集等介面或類別定義.

將這兩個 .jar 檔案加到 Classpath 或加入你所使用的 java IDE 工具的程式庫中就可以開始在你的 JAVA 應用程式中操作統計圖表了. (API 線上文件

開始第一個圖表 : 
我們先從一個簡單的 BarChart(長條圖) 開始吧! 這裡有一個銷售資料表, 接下來的例子就是要將這些資料顯示在 BarChart 上 : 
 

我們會在一個 JFrame 上顯示這個 BarChart, 所以程式一開始會 import java.awt.*, javax.swing.*. 而接著 import JFreeChart 所要用的類別 : 
- FirstBarChart.java 代碼 :
  1. package jfreechart;  
  2.   
  3. import javax.swing.JFrame;  
  4. import java.awt.*;  
  5. import org.jfree.chart.*;  
  6. import org.jfree.chart.axis.CategoryAxis;  
  7. import org.jfree.chart.axis.NumberAxis;  
  8. import org.jfree.chart.plot.*;  
  9. import org.jfree.chart.renderer.category.BarRenderer;  
  10. import org.jfree.data.*;  
  11. import org.jfree.data.category.CategoryDataset;  
  12. import org.jfree.data.category.DefaultCategoryDataset;  
  13.   
  14. public class FirstBarChart extends JFrame{  
  15.       
  16.     public FirstBarChart() {  
  17.         // 步驟1. 建立Dataset  
  18.         CategoryDataset dataset = setDataset();  
  19.         // 步驟2. 建立BarChart  
  20.         JFreeChart chart = createChart(dataset);  
  21.           
  22.         // 步驟3. 將所建立的 BarChart 放在 ChartPanel 上並設定大小.  
  23.         ChartPanel chartPanel = new ChartPanel(chart);  
  24.         chartPanel.setPreferredSize(new Dimension(500270));  
  25.         getContentPane().add(chartPanel);  
  26.         pack();  
  27.         setVisible(true);  
  28.         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  29.     }  
  30.       
  31.     private CategoryDataset setDataset() {  
  32.         String[] series = {"第一季""第二季""第三季"};  
  33.         String[] category = {"咖啡""啤酒""果汁""汽水""茶"};  
  34.         double[][] data = {{8.05.510.2}, {4.27.823.0}, {3.55.36.8}  
  35.         ,{9.214.510.7}, {6.68.37.9}};  
  36.         DefaultCategoryDataset dataset = new DefaultCategoryDataset();  
  37.         for(int i=0; i<category.length; i++)  
  38.             for(int j=0; j<series.length; j++)  
  39.                 dataset.addValue(data[i][j], series[j], category[i]);  
  40.         return dataset;  
  41.     }  
  42.   
  43.     private JFreeChart createChart(final CategoryDataset dataset) {  
  44.         JFreeChart chart = ChartFactory.createBarChart(  
  45.                 "2010第一季~第三季 銷售圖表"// 圖表標題   
  46.                 "產品類型"// X 軸標題  
  47.                 "銷售量(單位 : 萬箱)"// Y 軸標題  
  48.                 dataset, // dataset 物件變數  
  49.                 PlotOrientation.VERTICAL, // Bar 方向   
  50.                 true,  // 加入圖例說明  
  51.                 true,  // 顯示提示資料  
  52.                 false);// URLs?  
  53.         CategoryPlot categoryplot = (CategoryPlot) chart.getPlot();  
  54.         CategoryAxis domainAxis = categoryplot.getDomainAxis();  
  55.         NumberAxis numberaxis = (NumberAxis) categoryplot.getRangeAxis();  
  56.         numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());  
  57.         BarRenderer barrenderer = (BarRenderer) categoryplot.getRenderer();  
  58.         barrenderer.setBaseItemLabelFont(new Font("標楷體", Font.PLAIN, 12));  
  59.         barrenderer.setSeriesItemLabelFont(1new Font("標楷體", Font.PLAIN, 12));  
  60.   
  61.         /*------設置X軸座標上的文字-----------*/  
  62.         domainAxis.setTickLabelFont(new Font("sans-serif", Font.PLAIN, 11));  
  63.   
  64.         /*------設置X軸的標題文字------------*/  
  65.         domainAxis.setLabelFont(new Font("標楷體", Font.PLAIN, 12));  
  66.   
  67.         /*------設置Y軸座標上的文字-----------*/  
  68.         numberaxis.setTickLabelFont(new Font("sans-serif", Font.PLAIN, 12));  
  69.   
  70.         /*------設置Y軸的標題文字------------*/  
  71.         numberaxis.setLabelFont(new Font("黑体", Font.PLAIN, 12));  
  72.         chart.getLegend().setItemFont(new Font("標楷體", Font.PLAIN, 12));  
  73.         chart.getTitle().setFont(new Font("黑体", Font.BOLD, 14));  
  74.         return chart;  
  75.     }  
  76.       
  77.     public static void main(String args[]) {  
  78.         new FirstBarChart();  
  79.     }  
  80. }  

我們將在這個Class 的建構子中完成這個 BarChart 的主要流程 : 
1. 建立 CategoryDataset 資料集物件 : 
在建立統計圖表前, 我們先要把來源資料建立到圖表物件指定的Dataset 中. Barchart 指定 Dataset 是任何實做 org.jfree.data.category.CategoryDataset 介面的 Dataset 類別上, 因此我們建立一個 DefaultCategoryDataset 類別的實體, 並利用這個物件的 addValue 函式來填入統計資料.

2. 建立 BarChart 圖表物件 : 
JFreeChart 在 org.jfree.chart.ChartFactory 類別中提供一些方便的 static methods 可以讓 Programmer 將圖表物件建立起來, 這裡我們就用了 ChartFactory.createBarChart 來建立 BarChart 物件.

接著將這段程式碼執行後就會看到如下畫面 : 
 

介紹4個JFreeChart 常用圖表 : 
從上面例子中, 應該可以發現 BarChart 的處理方式是先將統計資料建立成 Dataset, 然後建立 BarChart 圖表物件, 透過這個物件來呈現 Dataset 中的資料, 接著將圖表物件放在 ChartPanel 上並設定 size, 再將 ChartPanel 加到 Frame, 顯示畫面即可看到效果. 其實 JFreeChart 所提供的幾個基本圖表物件在處理上大致雷同. 只是不同樣式的統計圖表, 底層對應的Dataset 就不太一樣, 裡面的資料結構也略有不同 ; 在建立圖表物件時, createXXXChart 函式的參數也有一些差別. 只要能掌握這些差異, 很快就能變化出不同的效果. 接下來我們就先把一些常用的圖表的Dataset 及 createXXXChart 函數整理出來, 以供參考 : 
* Bar Chart : 
- Dataset 介面 : org.jfree.data.category.CategoryDataset.
- 建立圖表 : org.jfree.chart.ChartFactory.createBarChart()

* Line Chart : 
- Dataset 介面 : org.jfree.data.category.CategoryDataset
填入資料用 method: addValue(numberValue, rowKey, colKey))
- 建立圖表 : ChartFactory.createLineChart()

* Pie Chart : 
- Dataset 介面 : org.jfree.data.category.CategoryToPieDataset
- 建立圖表 : ChartFactory.createPieChart()

* Time Series Chart : 所謂 Time Series Chart 即是以時間為軸, 將資料線性展開. 
- Dataset 介面 : org.jfree.data.xy.XYDataset
使用 new org.jfree.data.time.TimeSeriesCollection() 來建立物件, 填入資料用 method : addSeries(TimeSeries series)
- 建立圖表 : ChartFactory.createTimeSeriesChart

補充說明 : 
JFreeChat 中文亂碼、漢字亂碼的解決方案 
JavaWorld > JFreeChart pieChart 3D透明化問題 
Powerful Chart Engine-JFreeChart 實戰攻略(基礎心法篇)(上)

3 則留言:

  1. i,j的迴圈沒寫到的樣子,anyway thankz。

    回覆刪除
  2. 感謝提醒, 看來是HTML 識別字造成編碼錯誤 所以顯示異常 ><"

    回覆刪除
  3. i,j的迴圈我來補上 這是基本的common sense
    也謝謝puremonkey2010無私的經驗分享

    for(int i=0; i<5; i++)
    for(int j=0; j<3; j++)

    回覆刪除

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...