無為

          無為則可為,無為則至深!

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            190 Posts :: 291 Stories :: 258 Comments :: 0 Trackbacks
          JFreeChart,開放源碼的Java圖表生成組件(基于LGPL Licence),可以創建餅圖、 曲線圖、柱狀圖、甘特圖,生成PNG,JPG等圖片格式文件。當前最新版本為0.9.11,右邊是一張JFreeChart生成 的統計圖。本文講解如何在Web利用JFreeChart生成餅狀統計圖。

          不知道 JFreeChart 項目組出于什么目的,他們提供的 sample code 里面的例子給人感覺就是亂,同樣的結果可以用不同方式、使用不的方法。再加上網上流傳的 JFreeChart 舊的使用方法,使剛接觸 JFreeChart 的朋友進到 JFreeChart 中不花一些時間很難理出一個頭緒來。

          前面已經介紹過 JFreeChart 生成餅狀圖,可能由于上面提到的原因,有些朋友來信和留言希望介紹 JFreeChart 如何生成柱狀圖。抄襲別人一句話:Help others as well as to help myself。這次我們介紹使用 JFreeChart 生成柱狀圖,首先從一個最簡單的例子開始。

          一 最簡單的例子

          為了降低門檻,讓大家心理有個底,先介紹一個簡單的不能再簡單的例子,圖片中的各類屬性都采用默認值。

          <%@ page contentType="text/html;charset=GBK"%>
          <%@ page import="org.jfree.chart.ChartFactory,
                           org.jfree.chart.JFreeChart,
                           org.jfree.chart.plot.PlotOrientation,
                           org.jfree.chart.servlet.ServletUtilities,
                           org.jfree.data.DefaultCategoryDataset"%>
          <%
          DefaultCategoryDataset dataset = new DefaultCategoryDataset();
          dataset.addValue(300, "廣州", "蘋果");
          dataset.addValue(200, "廣州", "梨子");
          dataset.addValue(500, "廣州", "葡萄");
          dataset.addValue(340, "廣州", "芒果");
          dataset.addValue(280, "廣州", "荔枝");

          JFreeChart chart = ChartFactory.createBarChart3D("水果銷量統計圖",
                            "水果",
                            "銷量",
                            dataset,
                            PlotOrientation.VERTICAL,
                            false,
                            false,
                            false);

          String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, session);
          String graphURL = request.getContextPath() + "/servlet/DisplayChart?filename=" + filename;
          %>
          <img src="<%= graphURL %>" width=500 height=300 border=0 usemap="#<%= filename %>">

          這個 JSP 程序運行的結果如下圖


          圖 一

          二 柱狀圖高級特性

          上面的程序簡單,但生成的柱狀圖也很簡單。更多的時候,我們可能需要不同的效果。 org.jfree.chart.ChartFactory 這個工廠類有 createBarChart, createStackedBarChart, createBarChart3D, createStackedBarChart3D 這幾個工廠方法創建不同類型的柱狀圖。關于這四個方法的 JFreeChart 的 Java Doc API 文檔有詳細說明,比較重要的是 PlotOrientation.VERTICAL 讓平行柱垂直顯示,而 PlotOrientation.HORIZONTAL 則讓平行柱水平顯示。

          幾個對柱狀圖影響較大的幾個類,它們分別是:
          org.jfree.chart.axis.CategoryAxis
          org.jfree.chart.axis.ValueAxis
          org.jfree.chart.renderer.BarRenderer
          org.jfree.chart.renderer.BarRenderer3D

          我們還是以實例來說明這幾個類,先來假設一個需要統計的數據表:

            北京 上海 廣州 成都 深圳
          蘋果 672 766 223 540 126
          梨子 325 521 210 340 106
          葡萄 332 256 523 240 526

          根據上表數據,首先構造 CategoryDataset, 這里不再使用上面簡單例子里面的 DefaultCategoryDataset 類,而是 DatasetUtilities 更有效的構造 CategoryDataset,如下列代碼:

          double[][] data = new double[][] {{672, 766, 223, 540, 126}, {325, 521, 210, 340, 106}, {332, 256, 523, 240, 526}};
          String[] rowKeys = {"蘋果","梨子","葡萄"};
          String[] columnKeys = {"北京","上海","廣州","成都","深圳"};
          CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data);

          用上面的 dataset 生成的 3D 柱狀圖


          圖 二

          org.jfree.chart.axis.CategoryAxis

          CategoryAxis domainAxis = plot.getDomainAxis();
          //設置 columnKey 是否垂直顯示
          domainAxis.setVerticalCategoryLabels(true);
          //設置距離圖片左端距離
          domainAxis.setLowerMargin(0.1);
          //設置距離圖片右端距離
          domainAxis.setUpperMargin(0.1);
          //設置 columnKey 是否間隔顯示
          domainAxis.setSkipCategoryLabelsToFit(true);
          plot.setDomainAxis(domainAxis);

          上面代碼產生的效果如下圖,注意與圖二的區別。


          圖 三

          org.jfree.chart.axis.ValueAxis

          ValueAxis rangeAxis = plot.getRangeAxis();
          //設置最高的一個柱與圖片頂端的距離
          rangeAxis.setUpperMargin(0.15);
          //設置最低的一個柱與圖片底端的距離
          //rangeAxis.setLowerMargin(0.15);
          plot.setRangeAxis(rangeAxis);

          上面代碼產生的效果如下圖,注意與圖二的區別。


          圖 四

          org.jfree.chart.renderer.BarRenderer3D

          BarRenderer3D renderer = new BarRenderer3D();
          renderer.setBaseOutlinePaint(Color.BLACK);
          //設置 Wall 的顏色
          renderer.setWallPaint(Color.gray);
          //設置每種水果代表的柱的顏色
          renderer.setSeriesPaint(0, new Color(0, 0, 255));
          renderer.setSeriesPaint(1, new Color(0, 100, 255));
          renderer.setSeriesPaint(2, Color.GREEN);
          //設置每種水果代表的柱的 Outline 顏色
          renderer.setSeriesOutlinePaint(0, Color.BLACK);
          renderer.setSeriesOutlinePaint(1, Color.BLACK);
          renderer.setSeriesOutlinePaint(2, Color.BLACK);
          //設置每個地區所包含的平行柱的之間距離
          renderer.setItemMargin(0.1);
          //顯示每個柱的數值,并修改該數值的字體屬性
          renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator());
          renderer.setItemLabelFont(new Font("黑體",Font.PLAIN,12));
          renderer.setItemLabelsVisible(true);

          上面代碼產生的效果如下圖,注意與圖二的區別。


          圖 五

          補充兩個有用的方法

          補充 org.jfree.chart.plot.CategoryPlot 的兩個方法,這兩個方法對所有類型的圖表都有作用,因為在前面沒有介紹,這里補充一下。

          //設置地區、銷量的顯示位置
          plot.setDomainAxisLocation(AxisLocation.TOP_OR_RIGHT);
          plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);

          上面代碼產生的效果如下圖,注意與圖二的區別。


          圖 六

          三 完整范例

          前面都是一些代碼片段,現在把這些片段組合成一個完整范例。

          <%@ page contentType="text/html;charset=GBK"%>
          <%@ page import="java.awt.Color,
                          java.awt.Font,
                          org.jfree.chart.ChartFactory,
                          org.jfree.chart.JFreeChart,
                          org.jfree.chart.plot.PlotOrientation,
                          org.jfree.chart.servlet.ServletUtilities,
                          org.jfree.data.CategoryDataset,
                          org.jfree.data.DatasetUtilities,
                          org.jfree.chart.plot.CategoryPlot,
                          org.jfree.chart.axis.CategoryAxis,
                          org.jfree.chart.axis.ValueAxis,
                          org.jfree.chart.renderer.BarRenderer3D,
                          org.jfree.chart.labels.StandardCategoryItemLabelGenerator,
                          org.jfree.chart.axis.AxisLocation"%>
          <%
          double[][] data = new double[][] {{672, 766, 223, 540, 126},{325, 521, 210, 340, 106},{332, 256, 523, 240, 526}};
          String[] rowKeys = {"蘋果","梨子","葡萄"};
          String[] columnKeys = {"北京","上海","廣州","成都","深圳"};
          CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data);

          JFreeChart chart = ChartFactory.createBarChart3D("水果銷量圖統計",
                            null,
                            null,
                            dataset,
                            PlotOrientation.VERTICAL,
                            true,false,false);
          chart.setBackgroundPaint(Color.WHITE);
          CategoryPlot plot = chart.getCategoryPlot();

          CategoryAxis domainAxis = plot.getDomainAxis();
          domainAxis.setVerticalCategoryLabels(false);
          plot.setDomainAxis(domainAxis);

          ValueAxis rangeAxis = plot.getRangeAxis();
          //設置最高的一個 Item 與圖片頂端的距離
          rangeAxis.setUpperMargin(0.15);
          //設置最低的一個 Item 與圖片底端的距離
          rangeAxis.setLowerMargin(0.15);
          plot.setRangeAxis(rangeAxis);

          BarRenderer3D renderer = new BarRenderer3D();
          renderer.setBaseOutlinePaint(Color.BLACK);
          //設置 Wall 的顏色
          renderer.setWallPaint(Color.gray);
          //設置每種水果代表的柱的顏色
          renderer.setSeriesPaint(0, new Color(0, 0, 255));
          renderer.setSeriesPaint(1, new Color(0, 100, 255));
          renderer.setSeriesPaint(2, Color.GREEN);
          //設置每個地區所包含的平行柱的之間距離
          renderer.setItemMargin(0.1);
          //顯示每個柱的數值,并修改該數值的字體屬性
          renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator());
          renderer.setItemLabelsVisible(true);
          plot.setRenderer(renderer);

          //設置柱的透明度
          plot.setForegroundAlpha(0.6f);
          //設置地區、銷量的顯示位置
          plot.setDomainAxisLocation(AxisLocation.TOP_OR_RIGHT);
          plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);

          String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, session);
          String graphURL = request.getContextPath() + "/servlet/DisplayChart?filename=" + filename;
          %s>
          <img src="<%= graphURL %>" width=500 height=300 border=0 usemap="#<%= filename %>">

          看看程序運行的結果吧:


          圖 七

          三 總結

          我只介紹了少量的方法,更多的請參考 JFreeChart 的 Java Doc API 文檔和 Sample Code。文中的有些關于圖表的術語不知道該如何正確的表達,如果你有任何關于本文的想法,可以與我聯系 wayne@sentom.net.

          不知道 JFreeChart 項目組出于什么目的,他們提供的 sample code 里面的例子給人感覺就是亂,同樣的結果可以用不同方式、使用不的方法。再加上網上流傳的 JFreeChart 舊的使用方法,使剛接觸 JFreeChart 的朋友進到 JFreeChart 中不花一些時間很難理出一個頭緒來。

          前面已經介紹過 JFreeChart 生成餅狀圖,可能由于上面提到的原因,有些朋友來信和留言希望介紹 JFreeChart 如何生成柱狀圖。抄襲別人一句話:Help others as well as to help myself。這次我們介紹使用 JFreeChart 生成柱狀圖,首先從一個最簡單的例子開始。

          一 最簡單的例子

          為了降低門檻,讓大家心理有個底,先介紹一個簡單的不能再簡單的例子,圖片中的各類屬性都采用默認值。

          <%@ page contentType="text/html;charset=GBK"%>
          <%@ page import="org.jfree.chart.ChartFactory,
                           org.jfree.chart.JFreeChart,
                           org.jfree.chart.plot.PlotOrientation,
                           org.jfree.chart.servlet.ServletUtilities,
                           org.jfree.data.DefaultCategoryDataset"%>
          <%
          DefaultCategoryDataset dataset = new DefaultCategoryDataset();
          dataset.addValue(300, "廣州", "蘋果");
          dataset.addValue(200, "廣州", "梨子");
          dataset.addValue(500, "廣州", "葡萄");
          dataset.addValue(340, "廣州", "芒果");
          dataset.addValue(280, "廣州", "荔枝");

          JFreeChart chart = ChartFactory.createBarChart3D("水果銷量統計圖",
                            "水果",
                            "銷量",
                            dataset,
                            PlotOrientation.VERTICAL,
                            false,
                            false,
                            false);

          String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, session);
          String graphURL = request.getContextPath() + "/servlet/DisplayChart?filename=" + filename;
          %>
          <img src="<%= graphURL %>" width=500 height=300 border=0 usemap="#<%= filename %>">

          這個 JSP 程序運行的結果如下圖


          圖 一

          二 柱狀圖高級特性

          上面的程序簡單,但生成的柱狀圖也很簡單。更多的時候,我們可能需要不同的效果。 org.jfree.chart.ChartFactory 這個工廠類有 createBarChart, createStackedBarChart, createBarChart3D, createStackedBarChart3D 這幾個工廠方法創建不同類型的柱狀圖。關于這四個方法的 JFreeChart 的 Java Doc API 文檔有詳細說明,比較重要的是 PlotOrientation.VERTICAL 讓平行柱垂直顯示,而 PlotOrientation.HORIZONTAL 則讓平行柱水平顯示。

          幾個對柱狀圖影響較大的幾個類,它們分別是:
          org.jfree.chart.axis.CategoryAxis
          org.jfree.chart.axis.ValueAxis
          org.jfree.chart.renderer.BarRenderer
          org.jfree.chart.renderer.BarRenderer3D

          我們還是以實例來說明這幾個類,先來假設一個需要統計的數據表:

            北京 上海 廣州 成都 深圳
          蘋果 672 766 223 540 126
          梨子 325 521 210 340 106
          葡萄 332 256 523 240 526

          根據上表數據,首先構造 CategoryDataset, 這里不再使用上面簡單例子里面的 DefaultCategoryDataset 類,而是 DatasetUtilities 更有效的構造 CategoryDataset,如下列代碼:

          double[][] data = new double[][] {{672, 766, 223, 540, 126}, {325, 521, 210, 340, 106}, {332, 256, 523, 240, 526}};
          String[] rowKeys = {"蘋果","梨子","葡萄"};
          String[] columnKeys = {"北京","上海","廣州","成都","深圳"};
          CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data);

          用上面的 dataset 生成的 3D 柱狀圖


          圖 二

          org.jfree.chart.axis.CategoryAxis

          CategoryAxis domainAxis = plot.getDomainAxis();
          //設置 columnKey 是否垂直顯示
          domainAxis.setVerticalCategoryLabels(true);
          //設置距離圖片左端距離
          domainAxis.setLowerMargin(0.1);
          //設置距離圖片右端距離
          domainAxis.setUpperMargin(0.1);
          //設置 columnKey 是否間隔顯示
          domainAxis.setSkipCategoryLabelsToFit(true);
          plot.setDomainAxis(domainAxis);

          上面代碼產生的效果如下圖,注意與圖二的區別。


          圖 三

          org.jfree.chart.axis.ValueAxis

          ValueAxis rangeAxis = plot.getRangeAxis();
          //設置最高的一個柱與圖片頂端的距離
          rangeAxis.setUpperMargin(0.15);
          //設置最低的一個柱與圖片底端的距離
          //rangeAxis.setLowerMargin(0.15);
          plot.setRangeAxis(rangeAxis);

          上面代碼產生的效果如下圖,注意與圖二的區別。


          圖 四

          org.jfree.chart.renderer.BarRenderer3D

          BarRenderer3D renderer = new BarRenderer3D();
          renderer.setBaseOutlinePaint(Color.BLACK);
          //設置 Wall 的顏色
          renderer.setWallPaint(Color.gray);
          //設置每種水果代表的柱的顏色
          renderer.setSeriesPaint(0, new Color(0, 0, 255));
          renderer.setSeriesPaint(1, new Color(0, 100, 255));
          renderer.setSeriesPaint(2, Color.GREEN);
          //設置每種水果代表的柱的 Outline 顏色
          renderer.setSeriesOutlinePaint(0, Color.BLACK);
          renderer.setSeriesOutlinePaint(1, Color.BLACK);
          renderer.setSeriesOutlinePaint(2, Color.BLACK);
          //設置每個地區所包含的平行柱的之間距離
          renderer.setItemMargin(0.1);
          //顯示每個柱的數值,并修改該數值的字體屬性
          renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator());
          renderer.setItemLabelFont(new Font("黑體",Font.PLAIN,12));
          renderer.setItemLabelsVisible(true);

          上面代碼產生的效果如下圖,注意與圖二的區別。


          圖 五

          補充兩個有用的方法

          補充 org.jfree.chart.plot.CategoryPlot 的兩個方法,這兩個方法對所有類型的圖表都有作用,因為在前面沒有介紹,這里補充一下。

          //設置地區、銷量的顯示位置
          plot.setDomainAxisLocation(AxisLocation.TOP_OR_RIGHT);
          plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);

          上面代碼產生的效果如下圖,注意與圖二的區別。


          圖 六

          三 完整范例

          前面都是一些代碼片段,現在把這些片段組合成一個完整范例。

          <%@ page contentType="text/html;charset=GBK"%>
          <%@ page import="java.awt.Color,
                          java.awt.Font,
                          org.jfree.chart.ChartFactory,
                          org.jfree.chart.JFreeChart,
                          org.jfree.chart.plot.PlotOrientation,
                          org.jfree.chart.servlet.ServletUtilities,
                          org.jfree.data.CategoryDataset,
                          org.jfree.data.DatasetUtilities,
                          org.jfree.chart.plot.CategoryPlot,
                          org.jfree.chart.axis.CategoryAxis,
                          org.jfree.chart.axis.ValueAxis,
                          org.jfree.chart.renderer.BarRenderer3D,
                          org.jfree.chart.labels.StandardCategoryItemLabelGenerator,
                          org.jfree.chart.axis.AxisLocation"%>
          <%
          double[][] data = new double[][] {{672, 766, 223, 540, 126},{325, 521, 210, 340, 106},{332, 256, 523, 240, 526}};
          String[] rowKeys = {"蘋果","梨子","葡萄"};
          String[] columnKeys = {"北京","上海","廣州","成都","深圳"};
          CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data);

          JFreeChart chart = ChartFactory.createBarChart3D("水果銷量圖統計",
                            null,
                            null,
                            dataset,
                            PlotOrientation.VERTICAL,
                            true,false,false);
          chart.setBackgroundPaint(Color.WHITE);
          CategoryPlot plot = chart.getCategoryPlot();

          CategoryAxis domainAxis = plot.getDomainAxis();
          domainAxis.setVerticalCategoryLabels(false);
          plot.setDomainAxis(domainAxis);

          ValueAxis rangeAxis = plot.getRangeAxis();
          //設置最高的一個 Item 與圖片頂端的距離
          rangeAxis.setUpperMargin(0.15);
          //設置最低的一個 Item 與圖片底端的距離
          rangeAxis.setLowerMargin(0.15);
          plot.setRangeAxis(rangeAxis);

          BarRenderer3D renderer = new BarRenderer3D();
          renderer.setBaseOutlinePaint(Color.BLACK);
          //設置 Wall 的顏色
          renderer.setWallPaint(Color.gray);
          //設置每種水果代表的柱的顏色
          renderer.setSeriesPaint(0, new Color(0, 0, 255));
          renderer.setSeriesPaint(1, new Color(0, 100, 255));
          renderer.setSeriesPaint(2, Color.GREEN);
          //設置每個地區所包含的平行柱的之間距離
          renderer.setItemMargin(0.1);
          //顯示每個柱的數值,并修改該數值的字體屬性
          renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator());
          renderer.setItemLabelsVisible(true);
          plot.setRenderer(renderer);

          //設置柱的透明度
          plot.setForegroundAlpha(0.6f);
          //設置地區、銷量的顯示位置
          plot.setDomainAxisLocation(AxisLocation.TOP_OR_RIGHT);
          plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);

          String filename = ServletUtilities.saveChartAsPNG(chart, 500, 300, null, session);
          String graphURL = request.getContextPath() + "/servlet/DisplayChart?filename=" + filename;
          %s>
          <img src="<%= graphURL %>" width=500 height=300 border=0 usemap="#<%= filename %>">

          看看程序運行的結果吧:


          圖 七

          三 總結

           

          我只介紹了少量的方法,更多的請參考 JFreeChart 的 Java Doc API 文檔和 Sample Code。文中的有些關于圖表的術語不知道該如何正確的表達,如果你有任何關于本文的想法,可以與我聯系 wayne@sentom.net.



          凡是有該標志的文章,都是該blog博主Caoer(草兒)原創,凡是索引、收藏
          、轉載請注明來處和原文作者。非常感謝。

          posted on 2007-06-29 12:48 草兒 閱讀(2419) 評論(0)  編輯  收藏 所屬分類: Java編程經驗談eclipse
          主站蜘蛛池模板: 甘南县| 苏尼特右旗| 铜陵市| 海晏县| 岢岚县| 仪陇县| 连云港市| 琼结县| 通道| 曲阳县| 奈曼旗| 安徽省| 漯河市| 通城县| 玉林市| 治县。| 股票| 黑水县| 南平市| 潍坊市| 武强县| 尼勒克县| 云浮市| 额济纳旗| 库尔勒市| 阿合奇县| 永善县| 临安市| 万宁市| 泰州市| 开远市| 方山县| 洞口县| 克东县| 乐陵市| 昂仁县| 德钦县| 那曲县| 长子县| 逊克县| 福鼎市|