原文:http://blog.chinaunix.net/u/17663/showart_370064.html 一、簡介
WW 的發展使得基于因特網的應用程序不再局限于靜態或者簡單的動態內容提供。傳統的一些以軟件包形式發布應用程序例如報表系統等都在逐漸搬到因特網上。但是這兩者之間有著天壤之別,雖然對于數據獲取、業務處理等方面基本類似,但是最大的差別在于用戶界面。為了能在web瀏覽器上顯示要求用戶界面使用 HTML以及圖片的方式來展現數據,而傳統的一些利用操作系統本身的控件來開發的用戶界面無法適應琳瑯滿目的客戶端,因此在這里也變得無能為力。回到本文的題目上來,為了創建一個可以在web瀏覽器上查看到圖表一般有兩種做法:第一種就是使用applet利用java本身對圖形的支持來顯示一個圖表;第二種就是直接在web服務器端生成好圖表圖片文件后發送給瀏覽器。第一種方式顯然對于客戶端要求太高,隨著現在主流瀏覽器放棄對JAVA的支持后,這種方式只適合一些局域網的應用,而對于因特網的環境就顯得不太適合。因此我們下面將介紹一個JAVA的圖表引擎JFreeChart用來產生基于WEB的圖表。 JFreeChart 項目簡介 JFreeChart是開放源代碼站點SourceForge.net上的一個JAVA項目,它主要用來各種各樣的圖表,這些圖表包括:餅圖、柱狀圖(普通柱狀圖以及堆棧柱狀圖)、線圖、區域圖、分布圖、混合圖、甘特圖以及一些儀表盤等等。這些不同式樣的圖表基本上可以滿足目前的要求。 二、JFreeChart獲取。JFreeChart 是JFreeChart公司在開源網站SourceForge.net上的一個項目,該公司的主要產品有如下: 1.JFreeReport :報表解決工具 2.JFreeChart:Java 圖形解決方案(Application/Applet/Servlet/Jsp) 3.JCommon :JFreeReport和JFreeChart的公共類庫 4.JFreeDesigner :JFreeReport的報表設計工具 我們可以從jfree官方網站上獲取最新版本和相關資料(但是jfree的document需要40美金才能獲取), 獲取地址:http://www.jfree.org/jfreechart/index.html(同時可以獲得簡明介紹) 我們以當前最新版本:jfreechart-1.0.1.zip為例子進行說明。
三、JFreeChart配置安裝 1 、解壓jfreechart-1.0.1.zip.zip到指定位置,其中source是jfreechart的源碼,jfreechart-1.0.1-demo.jar 是例子程序,可以先運行一下看看各種效果,就知道他的nb之處了。 2 、為了配置成功,我們需要關注的文件有如下三個: 設置classpath。加入下面三個jar包。 jfreechart-1.0.1.jar 、jcommon-1.0.0.jar、gnujaxp.jar 加上第三個jar包有時web.xml會報錯,把它去掉就好了。 至此jfreechart的配置就完成了,下面就可以進行jfreechart的開發了。這里值得提出的是jfreechart的類 結構設計前后兼容性不是很好,不同版本的jfreechart中類庫結構可能不一樣,有時候可能需要查源碼。如果是中文顯示的時候可能依據觀感需要改變源碼的字體。 四、JFreeChart功能介紹 JFreeChart 目前是最好的java圖形解決方案,基本能夠解決目前的圖形方面的需求,主要包括如下幾個方面: pie charts (2D and 3D) :餅圖(平面和立體) bar charts (regular and stacked, with an optional 3D effect) :柱狀圖 line and area charts :曲線圖 scatter plots and bubble charts time series, high/low/open/close charts and candle stick charts :時序圖 combination charts :復合圖 Pareto charts Gantt charts :甘特圖 wind plots, meter charts and symbol charts wafer map charts ( 態圖表,餅圖(二維和三維) , 柱狀圖 ( 水平,垂直),線圖,點圖,時間變化圖,甘特圖, 股票行情圖,混和圖, 溫度計圖, 刻度圖等常用商用圖表) 圖形可以導出成PNG和JPEG格式,同時還可以與PDF和EXCEL關聯 JFreeChart 核心類庫介紹: 研究jfreechart源碼發現源碼的主要由兩個大的包組成:org.jfree.chart,org.jfree.data。其中前者主要與圖形 本身有關,后者與圖形顯示的數據有關。具體研究如果大家有興趣的話可以自己研究 。 核心類主要有: org.jfree.chart.JFreeChart :圖表對象,任何類型的圖表的最終表現形式都是在該對象進行一些屬性的定制。JFreeChart引擎本身提供了一個工廠類用于創建不同類型的圖表對象 org.jfree.data.category.XXXDataSet: 數據集對象,用于提供顯示圖表所用的數據。根據不同類型的圖表對應著很多類型的數據集對象類 org.jfree.chart.plot.XXXPlot :圖表區域對象,基本上這個對象決定著什么樣式的圖表,創建該對象的時候需要Axis、Renderer以及數據集對象的支持 org.jfree.chart.axis.XXXAxis :用于處理圖表的兩個軸:縱軸和橫軸 org.jfree.chart.render.XXXRender :負責如何顯示一個圖表對象 org.jfree.chart.urls.XXXURLGenerator: 用于生成Web圖表中每個項目的鼠標點擊鏈接 XXXXXToolTipGenerator: 用于生成圖象的幫助提示,不同類型圖表對應不同類型的工具提示類 個人感覺JFreeChart可以滿足大部分圖片創建的需要,美中不足的是:對字體的設置做的不夠好,特別是使用中文的時候字體很不清晰。因為這個原因建議你自己去修改他的源代碼,最好使用properties文件去設置字體.還有就是文檔要錢所以要多花點時間去看源代碼。或多上社區. 五.開始開發 對JfreeChart有了初步了解并做好準備工作之后,開始作例子程序試驗。在這里我只介紹餅圖的做法,而這張圖采用不同的方式進行輸出,其他類型的圖片可以參考jfreechart提供的例子,做法都差不多。 1) 直接生成圖片
代碼 - public?class?PieChartPicture?{??
- public?static?void?main(String[]?args)???
- {??
- ?PieDataset?dataset?=?getDataSet();??
- ?JFreeChart?chart?=?ChartFactory.createPieChart3D(??
- ????"?項目進度分布",???
- ????dataset,??
- ????true,??
- ????true,??
- ????false??
- ???);??
- ??PiePlot3D??plot=(PiePlot3D)chart.getPlot();??
- ??????
- ??????
- ??
- ?plot.setLabelGenerator(new?StandardPieSectionLabelGenerator("{0}={1}({2})",?NumberFormat.getNumberInstance(),?new?DecimalFormat("0.00%")));???
- ??
- ?plot.setLegendLabelGenerator(new?StandardPieSectionLabelGenerator("{0}={1}({2})"));???
- ??
- chart.setBackgroundPaint(Color.white);???
- ??
- ?plot.setForegroundAlpha(1.0f);???
- ??
- plot.setCircular(true);???
- ??
- Font?font?=?new?Font("?黑體",Font.CENTER_BASELINE,20);???
- TextTitle?title?=?new?TextTitle("?項目狀態分布");???
- title.setFont(font);????
- chart.setTitle(title);???
- FileOutputStream?fos_jpg?=?null;???
- try?{???
- ?????fos_jpg=new?FileOutputStream("D:\\?項目狀態分布.jpg");???
- ?????ChartUtilities.writeChartAsJPEG(fos_jpg,100,chart,640,480,null);???
- ?????fos_jpg.close();???
- }?catch?(Exception?e)?{???
- ?}???
- }???
- private?static?PieDataset?getDataSet()?{???
- DefaultPieDataset?dataset?=?new?DefaultPieDataset();???
- dataset.setValue("?市場前期",?new?Double(10));???
- dataset.setValue("?立項",?new?Double(15));???
- dataset.setValue("?計劃",?new?Double(10));???
- dataset.setValue("?需求與設計",?new?Double(10));???
- dataset.setValue("?執行控制",?new?Double(35));???
- dataset.setValue("?收尾",?new?Double(10));???
- dataset.setValue("?運維",new?Double(10));???
- return?dataset;??????????
- }??
- }???
2) 采用servlet和struts的action方式輸出 采用這種方式輸出,不用生成圖片。 A .servlet輸出
代碼 - public?class?PieByServlet?extends?HttpServlet{???
- public?void?service(ServletRequest?req,?ServletResponse?res)???
- throws?ServletException,?IOException???
- {???
- ???res.setContentType("image/jpeg");???
- ???PieDataset?dataset?=?getDataSet();???
- ???JFreeChart?chart?=?ChartFactory.createPieChart3D(???
- ???"?水果餅圖",???
- ???dataset,??
- ???true,???
- ???true,???
- ???false?);???
- ?????
- ??
- ?ChartUtilities.writeChartAsJPEG(res.getOutputStream(),100,chart,800,600,null);???
- }???
B .struts的action方式輸出 只將這條語句加上try catch即可,并返回null。 代碼 - try{?????????
- ChartUtilities.writeChartAsJPEG(response.getOutputStream(),100,chart,800,600,null);???
- ?}?catch?(Exception?e)?{???
- }??
- return?null;???
其實采用這兩種方式與生成圖片的方式改動并不大 加上語句response.setContentType("image/jpeg"); ChartUtilities.writeChartAsJPEG(new FileOutputStream("D:\\ 項目狀態分布.jpg");,100,chart,640,480,null); 文件流改成response的輸出流就可以了 hartUtilities.writeChartAsJPEG(response.getOutputStream(),100,chart,800,600,null); 3)jsp+servlet+javabean方式 1. Create ChartViewer servlet
代碼 - public?class?ChartViewer?extends?HttpServlet?{???
- public?void?init()?throws?ServletException?{??
- }???
- ??
- public?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)??throws?ServletException,?IOException?{???
- ??
- HttpSession?session?=?request.getSession();???
- BufferedImage?chartImage?=?(BufferedImage)?session.getAttribute("chartImage");???
- ??
- response.setContentType("image/png");???
- ??
- PngEncoder?encoder?=?new?PngEncoder(chartImage,?false,?0,?9);???
- response.getOutputStream().write(encoder.pngEncode());??
- }???
- ??
- public?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)??throws?ServletException,?IOException?{???
- doGet(request,?response);???
- }???
- ??
- public?void?doPut(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{???
- }???
- ??
- public?void?destroy()?{?}???
- }???
2. Create a servlet map in web.xml
代碼 - <?xml?version="1.0"?encoding="UTF-8"?>???
- <web-app>???
- ?<servlet>???
- ?<servlet-name>ChartViewer</servlet-name>???
- ?<servlet-class>myapp.webwork.servlets.ChartViewer</servlet-class>???
- </servlet>???
- <servlet-mapping>???
- <servlet-name>ChartViewer</servlet-name>???
- <url-pattern>/servlet/ChartViewer</url-pattern>???
- </servlet-mapping>???
- </web-app>???
3. Create a chart in a java bean (Pie3DDemo.java) 代碼 - public?class?Pie3DDemo?{???
- private?DefaultPieDataset?getDataset()?{???
- ??
- String[]?section?=?new?String[]?{?"Jan","Feb","Mar","Apr","May","Jun",?"Jul","Aug","Sep","Oct","Nov","Dec"?};???
- ??
- double[]?data?=?new?double[section.length];???
- ?for?(int?i?=?0;?i?<?data.length;?i++)?{???
- ?????data[i]?=?10?+?(Math.random()?*?10);???
- }???
- ??
- DefaultPieDataset?dataset?=?new?DefaultPieDataset();???
- for?(int?i?=?0;?i?<?data.length;?i++)?{???
- ???????dataset.setValue(section[i],?data[i]);???
- }???
- return?dataset;???
- }???
- public?String?getChartViewer(HttpServletRequest?request,?HttpServletResponse?response)?{???
- ?DefaultPieDataset?dataset?=?getDataset();???
- ??
- ?JFreeChart?chart?=?ChartFactory.createPie3DChart(???
- ??"Pie3D?Chart?Demo",????
- ??dataset,???????????????
- ??true,??????????????????
- ??true,???
- ??false???
- ?);???
- ??
- chart.setBackgroundPaint(Color.cyan);???
- PiePlot?plot?=?(PiePlot)?chart.getPlot();???
- plot.setNoDataMessage("No?data?available");???
- ??
- ?plot.setURLGenerator(new?StandardPieURLGenerator("Bar3DDemo.jsp","section"));???
- plot.setLabelGenerator(null);???
- ??
- ChartRenderingInfo?info?=?null;???
- HttpSession?session?=?request.getSession();???
- try?{???
- ??
- ?response.setContentType("text/html");???
- ?info?=?new?ChartRenderingInfo(new?StandardEntityCollection());???
- ?BufferedImage?chartImage?=?chart.createBufferedImage(640,?400,?info);???
- ??
- ??
- session.setAttribute("chartImage",?chartImage);???
- PrintWriter?writer?=?new?PrintWriter(response.getWriter());???
- ChartUtilities.writeImageMap(writer,?"imageMap",?info);???
- writer.flush();???
- }?catch?(Exception?e)?{?}???
- ??
- String?pathInfo?=?"http://";???
- pathInfo?+=?request.getServerName();???
- int?port?=?request.getServerPort();???
- pathInfo?+=?":"+String.valueOf(port);???
- pathInfo?+=?request.getContextPath();???
- String?chartViewer?=?pathInfo?+?"/servlet/ChartViewer";???
- return?chartViewer;???
- }???
6. 頁面
代碼 - ???
- <html>???
- <head>???
- <title>Pie?Chart?Demo</title>???
- </head>???
- <jsp:useBeanidjsp:useBeanid="myChart"scope="session"class="myapp.webwork.beans.Pie3DDemo"?/>???
- <body>???
- <h2>Pie?Chart?Demo</h2>???
- <%String?chartViewer?=?myChart.getChartViewer(request,?response);%>???
- <img?src="<%=chartViewer%>"?border=0?usemap="#imageMap">???
- </body>???
- </html>???
4)采用工具類ChartUtil和DisplayChart(jfreechart的servlet)輸出 我用了上面的幾個方法輸出圖片,發現頁面里只能輸出一個圖片, 不過下面的方法可以輸出多個圖片,而且是幾種方式中最簡單的一個,推薦使用。 這種方式和上面的三種比較類似,是將javabean里的生成圖片的方法寫的一個工具類ChartUtil里面。 1 .添加工具類ChartUtil public class ChartUtil { // 產生時間序列圖,返回圖片名稱
代碼 - public??static?String?generatePieChart(DefaultPieDataset?dataset,String?title,int?width,int?height,HttpSession?session,?PrintWriter?pw)?{???
- ??
- String?filename?=?null;???
- ?try?{???
- ?if?(session?!=?null)???
- ?{???
- ChartDeleter?deleter?=?(ChartDeleter)session.getAttribute("JFreeChart_Deleter");???
- ?session.removeAttribute("JFreeChart_Deleter");???
- ?session.setAttribute("JFreeChart_Deleter",?deleter);???
- }???
- JFreeChart?chart?=?ChartFactory.createPieChart3D(???
- title,????
- dataset,???
- true,????
- true,???
- false?);???
- ??
- ChartRenderingInfo?info?=?new?ChartRenderingInfo(new?StandardEntityCollection());???
- ??
- ??
- filename?=?ServletUtilities.saveChartAsPNG(chart,?width,?height,?info,?session);???
- ??
- ?ChartUtilities.writeImageMap(pw,?filename,?info,true);???
- ?pw.flush();???
- }?catch?(Exception?e)?{???
- ?System.out.println("Exception?-?"?+?e.toString());???
- ?e.printStackTrace(System.out);???
- ?filename?=?"picture_error.png";?}???
- return?filename;???
- }???
- }???
2、在action里統計數據,設置好數據集dataset。傳到頁面 3、 在頁面里取出 DefaultPieDataset piedataset=(DefaultPieDataset)request.getAttribute("piedataset"); // 用ChartUtil工具類產生圖片
代碼 - String?p?=?ChartUtil.generatePieChart(piedataset,"?項目收支線圖",500,300,null,?new?PrintWriter(out));???
- String?p1?=?request.getContextPath()?+?"/servlet/DisplayChart?filename="?+?p;???
通過以下方式輸出 代碼 - <td><img?src="<%=?p1?%>"?width=500?height=300?border=0?usemap="#<%=?p?%>"></td>??
4、在web.xml中添加
代碼 - <servlet>??
- ??<servlet-name>DisplayChart</servlet-name>??
- ??<servlet-class>org.jfree.chart.servlet.DisplayChart</servlet-class>??
- </servlet>??
- <servlet-mapping>??
- ????<servlet-name>DisplayChart</servlet-name>??
- ????<url-pattern>/servlet/DisplayChart</url-pattern>??
- </servlet-mapping>??
5) ApplicationFrame 方式
代碼 - public?class?PieChartDemo1?extends?ApplicationFrame?{???
- public?PieChartDemo1(String?title)?{???
- super(title);???
- setContentPane(createDemoPanel());???
- }???
- private?static?JFreeChart?createChart(PieDataset?dataset)?{???
- JFreeChart?chart?=?ChartFactory.createPieChart(???
- .......??
- return?chart;???
- }???
- ??
- public?static?JPanel?createDemoPanel()?{???
- JFreeChart?chart?=?createChart(createDataset());???
- return?new?ChartPanel(chart);???
- }???
- ??
- public?static?void?main(String[]?args)?{???
- PieChartDemo1?demo?=?new?PieChartDemo1("Pie?Chart?Demo?1");???
- demo.pack();???
- RefineryUtilities.centerFrameOnScreen(demo);???
- demo.setVisible(true);???
- }???
- }???
六. 可參考資料與網址 官方網站 http://www.jfree.org/jfreechart/index.html 官方論壇 http://www.jfree.org/phpBB2/index.php API 文檔 http://www.jfree.org/jfreechart/api/gjdoc/index.html 中文API http://blog.sina.com.cn/u/405da78d010000ap
|
|