2008年9月22日 星期一

[Java] 免費的統計數據圖 library -- JFreeChart

snap003
還好有 Survey, 要不然真的要自己寫了...... , 這是免費的繪製曲線圖 library
本文內容大綱如下:
  1. 一般 JDK 的編譯設定
  2. BarChart JDK 編譯教學
  3. XYPlot JDK 編譯教學 (source code 內附範例)
  4. TimeSeriesChart JDK 編譯教學 (source code 內附範例)
  5. JBuilder 的編譯設定
  6. 網路上 JFreeChart 範例程式大集合
  7. 網路上其他作者探討 JFreeChart 效能的問題
  8. 延伸閱讀包含另一個類似的東西: 新一代的網站圖表工具 -- XML/SWF Charts
  9. 中文問題的處理

相關資源
簡單的教學: http://www-128.ibm.com/developerworks/cn/java/l-jfreechart/   (因為原作者自己寫的教學要錢, 所以很多人都有寫教學.)

如果你對 Android 有興趣, 可以參考 afreechart 專案
- afreechart project: http://code.google.com/p/afreechart/

你能用 JFreeChart 做到的事情
  PriceVolumeDemo1-254.png PopulationChartDemo1-254.png DifferenceChartDemo2-254.png DualAxisDemo1-254.png ScatterPlotDemo1-254.png  HistogramDemo1-254.png   DialPlotDemo2a_254.png


如何編譯最簡單範例    (下面總共介紹 三 個範例)
      這是一個問題, 因為官方網站的手冊要錢, 所以只好到網路上去找範例.

1. 網路上最簡單範例.
我做了些修正, 讓這個範例能夠在 1.0.11 版的今天能夠順利的編譯成功
內文如下:
---------------------- BarChartDemo.java ---------------------
// 這個範例是修改自 http://www-128.ibm.com/developerworks/cn/java/l-jfreechart/
// 原因: 
//      使用這篇文件已經過時了, 在目前 jfreechart-1.0 版本下無法編譯成功
//  主要修改部分
//       1. 文字 由簡體中文改成 英文
//       2. import org.jfree.data  -> import org.jfree.data.category.*;
//       3. ChartUtilities.writeChartAsJPEG(fos_jpg,100f,chart,400,300,null); 改成
//           ChartUtilities.writeChartAsJPEG(fos_jpg,1.0f,chart,400,300,null);
//       4. 程式架構改成物件呼叫
(井民全修正)

import java.io.*;
import org.jfree.data.*;
import org.jfree.data.category.*;  
import org.jfree.chart.*;
import org.jfree.chart.plot.*;

public class BarChartDemo{
    public static void main(String[] args) throws IOException{
        Demo mychart=new Demo();
        mychart.run();
    }
}

class Demo{
    public void run()throws IOException{
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        dataset.addValue(100, "Miaoli", "Car");
        dataset.addValue(200, "Taipei", "Moto"); 
        dataset.addValue(300, "Hsinchu", "Bicycle");
        dataset.addValue(400, "Hualien", "Car");
        dataset.addValue(500, "Kaohsiung", "Moto");
        JFreeChart chart = ChartFactory.createBarChart3D(
                            "Title", // 圖的標題
                            "city",  // x 座標標題
                            "value", // y 座標標題
                            dataset, // 你放數據的地方
                            PlotOrientation.VERTICAL, // 圖表方向:水平、垂直
                            true,     // 是否顯示圖例
                            false,     // 是否 tooltips 工具 
                            false     // 是否生成URL
                            );
        FileOutputStream fos_jpg = null;
        try {
            fos_jpg = new FileOutputStream("fruit.jpg");
            ChartUtilities.writeChartAsJPEG(fos_jpg,1.0f,chart,400,300,null);
        } finally {
            try {
                fos_jpg.close();
            } catch (Exception e) {}
        }
    }
}

------------------------------------------------------------------
最簡單的編譯方式:
Step 1: 解開 jfreechart-1.0.11.zip
Step 2: 建立 make.bat
javac -encoding Big5 -cp .;.\jfreechart-1.0.11\lib\jfreechart-1.0.11.jar;.\jfreechart-1.0.11\lib\jcommon-1.0.14.jar;.\jfreechart-1.0.11\lib\gnujaxp.jar;.\jfreechart-1.0.11\lib\servlet.jar;.\jfreechart-1.0.11\lib\junit.jar BarChartDemo.java

Step 3: 建立 run.bat
java -cp .;.\jfreechart-1.0.11\lib\jfreechart-1.0.11.jar;.\jfreechart-1.0.11\lib\jcommon-1.0.14.jar;.\jfreechart-1.0.11\lib\gnujaxp.jar;.\jfreechart-1.0.11\lib\servlet.jar;.\jfreechart-1.0.11\lib\junit.jar BarChartDemo

Step 4: 把 run.bat, BarChartDemo.java, make.bat 放在 jfreechart-1.0.11 相同目錄下.
 例如:
      c:\test\jfreechart-1.0.11   (這是 library 目錄)
      c:\test\run.bat
      c:\test\BarChartDemo.java
      c:\test\make.bat

Step 5: 執行 make.bat       
Step 6: 執行測試  run.bat      

BarChartDemo.java  完整專案

範例程式執行的結果
fruit

2. JFreeChart library 的範例 1
其實在 jfreechart-1.0.11\experimental 裡面, 附有一些範例可以拿來參考.
例如在目錄  jfreechart-1.0.11\experimental\org\jfree\experimental\chart\demo 裡面就有CombinedXYPlotDemo1.java
可是要怎麼編譯與執行呢?   嗯... 現在教你.
Step 1: 解開 jfreechart-1.0.11.zip
Step 2: 撰寫 make_CombinedXYPlotDemo1.bat
--------------------make_CombinedXYPlotDemo1.bat-----------------
javac -encoding Big5 -cp .;.\jfreechart-1.0.11\experimental;.\jfreechart-1.0.11\lib\jfreechart-1.0.11.jar;.\jfreechart-1.0.11\lib\jcommon-1.0.14.jar;.\jfreechart-1.0.11\lib\gnujaxp.jar;.\jfreechart-1.0.11\lib\servlet.jar;.\jfreechart-1.0.11\lib\junit.jar .\jfreechart-1.0.11\experimental\org\jfree\experimental\chart\demo\CombinedXYPlotDemo1.java
---------------------------------------------------------------------------------

Step 3: 撰寫 run_CombinedXYPlotDemo1.bat
--------------------run_CombinedXYPlotDemo1.bat-----------------
java -cp .;.\jfreechart-1.0.11\experimental;.\jfreechart-1.0.11\lib\jfreechart-1.0.11.jar;.\jfreechart-1.0.11\lib\jcommon-1.0.14.jar;.\jfreechart-1.0.11\lib\gnujaxp.jar;.\jfreechart-1.0.11\lib\servlet.jar;.\jfreechart-1.0.11\lib\junit.jar org.jfree.experimental.chart.demo.CombinedXYPlotDemo1
---------------------------------------------------------------------------------

Step 4: 把 make_CombinedXYPlotDemo1.bat, run_CombinedXYPlotDemo1.bat放在 jfreechart-1.0.11 相同目錄下.
 例如:
      c:\test\jfreechart-1.0.11   (這是 library 目錄)
      c:\test\run_CombinedXYPlotDemo1.bat 
      c:\test\make_CombinedXYPlotDemo1.bat

Step 5: 編譯
       請用滑鼠點選 make_CombinedXYPlotDemo1.bat
Step 6: 執行
      請用滑鼠點選 run_CombinedXYPlotDemo1.bat

範例程式執行的結果
snap003

3. JFreeChart library 範例 2
其實在 jfreechart-1.0.11\source 裡面, 附有一些範例可以拿來參考.
ex:
.\jfreechart-1.0.11\source\org\jfree\chart\demo\TimeSeriesChartDemo1.java
編譯的方式為
Step 1: 解開 jfreechart-1.0.11.zip
Step 2: 撰寫 make_TimeSeriesChartDemo1.bat
--------------------make_TimeSeriesChartDemo1.bat-----------------
javac -cp .;.\jfreechart-1.0.11\source;.\jfreechart-1.0.11\lib\jfreechart-1.0.11.jar;.\jfreechart-1.0.11\lib\jcommon-1.0.14.jar;.\jfreechart-1.0.11\lib\gnujaxp.jar;.\jfreechart-1.0.11\lib\servlet.jar;.\jfreechart-1.0.11\lib\junit.jar .\jfreechart-1.0.11\source\org\jfree\chart\demo\TimeSeriesChartDemo1.java
---------------------------------------------------------------------------------

Step 3: 撰寫 run_TimeSeriesChartDemo1.bat
--------------------run_TimeSeriesChartDemo1.bat-----------------
java -cp .;.\jfreechart-1.0.11\source;.\jfreechart-1.0.11\lib\jfreechart-1.0.11.jar;.\jfreechart-1.0.11\lib\jcommon-1.0.14.jar;.\jfreechart-1.0.11\lib\gnujaxp.jar;.\jfreechart-1.0.11\lib\servlet.jar;.\jfreechart-1.0.11\lib\junit.jar org.jfree.chart.demo.TimeSeriesChartDemo1
---------------------------------------------------------------------------------

Step 4: 把 make_TimeSeriesChartDemo1..bat, run_TimeSeriesChartDemo1..bat放在 jfreechart-1.0.11 相同目錄下.
 例如:
      c:\test\jfreechart-1.0.11   (這是 library 目錄)
      c:\test\make_TimeSeriesChartDemo1.bat  
      c:\test\run_TimeSeriesChartDemo1.bat

Step 5: 編譯
       請用滑鼠點選 make_TimeSeriesChartDemo1.bat
Step 6: 執行
      請用滑鼠點選 run_TimeSeriesChartDemo1.bat

範例程式執行的結果
snap003

JBuilder 設定
如果你使用 JBuilder 編譯你的專案, 那麼你會需要建立一個 library, 詳細作法如下:
      Step 1: 新增一個 library: jfreechart
       JB9 操作: [Tools]->[Configure Libaries...] -> [New...]
                           輸入 jfreechart
        Step 2: 加入設定你的 jfreechart 中 lib 目錄裡面的各項 .jar 位置
         JB9 操作: 到右邊的面版, 點選 [Add]
         ex:
                                  snap003
     完成.
   
現在你已經會編譯了, 接下來該是看別人寫程式碼的時候了
其他重要範例程式碼 (JFreeChart 範例程式大集合)



探討 JFreeChart 的效能問題

中文問題的處理:
上面介紹的程式無法處理中文, 現在的情況是所有的中文會變成 口. 如何修正呢?
根據網友 "中華英雄" 的提醒:
必須使用自己建構 plot 元件, 這樣 中文標題才不會有顯示的問題. 以折線圖為例, 作法如下
把上面的方便函示 createXYLineChart :
final JFreeChart chart = ChartFactory.createXYLineChart(
       strTitle,
       xTitle,
       yTitle, // "Dark Point Count",
       data,
       orientation,
       true,
       true,
       false
       );
換成這樣:
--------------------------------------------------------------
XYItemRenderer renderer1;
renderer1 = new XYLineAndShapeRenderer(true, false); // 折線圖 
Number domainAxis = new NumberAxis("中文 x 軸");// 建立 X 座標 
NumberAxis rangeAxis = new NumberAxis("中文 y 軸");// 建立 y 座標
//  改變 X 座標軸屬性:  自動範圍不包含 0
// 一定要加這個, 否則當你做動態折線圖時的 x 座標將不會移動
domainAxis.setAutoRangeIncludesZero(false);
// 建立 plot 物件, 並且指定好 x 與 y 座標元件
XYPlot plot = new XYPlot(data, domainAxis, rangeAxis, renderer1);  
plot.setBackgroundPaint(Color.lightGray); // 背景 
plot.setDomainGridlinePaint(Color.white); // 垂直虛線 座標軸的顏色  
plot.setRangeGridlinePaint(Color.white); //  水平虛線的顏色 
JFreeChart chart = new JFreeChart(strTitle, JFreeChart.DEFAULT_TITLE_FONT,plot, true);
--------------------------------------------------------------

Enjoy.
by Jing

延伸閱讀

4 則留言:

  1. 中文會變成 口.

    JFreeChart chart = ChartFactory.createPieChart3D("水果產量圖", // 圖表標題
    data,
    true, // 是否顯示圖例
    false,
    Locale.TAIWAN
    );
    //以上這種寫法會口口口

    PiePlot3D plot = new PiePlot3D(data);
    plot.setInsets(new RectangleInsets(0.0, 5.0, 5.0, 5.0));

    plot.setBackgroundAlpha(0.6f);

    plot.setForegroundAlpha(0.60f);

    JFreeChart chart = new JFreeChart("title", JFreeChart.DEFAULT_TITLE_FONT,
    plot, true);
    //以上這種寫法就不會都口口口了

    回覆刪除
  2. 請教您一些問題,是關於您的<1. 網路上最簡單範例.>
    我不會用lib
    您說的c:\test\jfreechart-1.0.11 (這是 library 目錄)
    是指jfreechart-1.0.11資料夾裡面的lib放到跟程式同個資料夾就好了嗎?謝謝。

    回覆刪除
  3. 如果你仔細看一下我寫的 make.bat 內容, 你會發現路徑全部是相對於 jfreechart-1.0.11\

    所以如果你的 JFreeChart 放在 c:\test\jfreechart-1.0.11\

    那麼把我寫的那幾個 bat 當放在 c:\test\jfreechart-1.0.11\

    然後, 滑鼠 double clicked make.bat 會自動編譯

    回覆刪除