转载 :Java图表解决方案:Jfreechart - 小何贝贝的技术空间 - 51CTO技术博客.

为了创建一个可以在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) 直接生成图片

Java代码 复制代码
  1. publicclass PieChartPicture {
  2. publicstaticvoid main(String[] args)
  3. {
  4. PieDataset dataset = getDataSet();
  5. JFreeChart chart = ChartFactory.createPieChart3D(
  6. " 项目进度分布", // chart title
  7. dataset,// data
  8. true,// include legend
  9. true,
  10. false
  11. );
  12. PiePlot3D  plot=(PiePlot3D)chart.getPlot();
  13. // 图片中显示百分比:默认方式
  14. //plot.setLabelGenerator(new           StandardPieSectionLabelGenerator(StandardPieToolTipGenerator.DEFAULT_TOOLTIP_FORMAT));
  15. // 图片中显示百分比:自定义方式,{0} 表示选项, {1} 表示数值, {2} 表示所占比例 ,小数点后两位
  16. plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}={1}({2})", NumberFormat.getNumberInstance(), new DecimalFormat("0.00%")));
  17. // 图例显示百分比:自定义方式, {0} 表示选项, {1} 表示数值, {2} 表示所占比例
  18. plot.setLegendLabelGenerator(new StandardPieSectionLabelGenerator("{0}={1}({2})"));
  19. // 设置背景色为白色
  20. chart.setBackgroundPaint(Color.white);
  21. // 指定图片的透明度(0.0-1.0)
  22. plot.setForegroundAlpha(1.0f);
  23. // 指定显示的饼图上圆形(false)还椭圆形(true)
  24. plot.setCircular(true);
  25. // 设置图标题的字体
  26. Font font = new Font(" 黑体",Font.CENTER_BASELINE,20);
  27. TextTitle title = new TextTitle(" 项目状态分布");
  28. title.setFont(font);
  29. chart.setTitle(title);
  30. FileOutputStream fos_jpg = null;
  31. try {
  32. fos_jpg=new FileOutputStream("D:\\ 项目状态分布.jpg");
  33. ChartUtilities.writeChartAsJPEG(fos_jpg,100,chart,640,480,null);
  34. fos_jpg.close();
  35. } catch (Exception e) {
  36. }
  37. }
  38. privatestatic PieDataset getDataSet() {
  39. DefaultPieDataset dataset = new DefaultPieDataset();
  40. dataset.setValue(" 市场前期", new Double(10));
  41. dataset.setValue(" 立项", new Double(15));
  42. dataset.setValue(" 计划", new Double(10));
  43. dataset.setValue(" 需求与设计", new Double(10));
  44. dataset.setValue(" 执行控制", new Double(35));
  45. dataset.setValue(" 收尾", new Double(10));
  46. dataset.setValue(" 运维",new Double(10));
  47. return dataset;
  48. }
  49. }



2) 采用servlet和struts的action方式输出
采用这种方式输出,不用生成图片。 
A .servlet输出 

Java代码 复制代码
  1. publicclass PieByServlet extends HttpServlet{
  2. publicvoid service(ServletRequest req, ServletResponse res)
  3. throws ServletException, IOException
  4. {
  5. res.setContentType("image/jpeg");
  6. PieDataset dataset = getDataSet();
  7. JFreeChart chart = ChartFactory.createPieChart3D(
  8. " 水果饼图", // chart title
  9. dataset,// data
  10. true, // include legend
  11. true,
  12. false );
  13. //设置图表属性
  14. // 输出图片
  15. ChartUtilities.writeChartAsJPEG(res.getOutputStream(),100,chart,800,600,null);
  16. }


B .struts的action方式输出 
只将这条语句加上try catch即可,并返回null。 

Java代码 复制代码
  1. try{
  2. ChartUtilities.writeChartAsJPEG(response.getOutputStream(),100,chart,800,600,null);
  3. } catch (Exception e) {
  4. }
  5. returnnull;



其实采用这两种方式与生成图片的方式改动并不大 
加上语句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 

Java代码 复制代码
  1. publicclass ChartViewer extends HttpServlet {
  2. publicvoid init() throws ServletException {
  3. }
  4. //Process the HTTP Get request
  5. publicvoid doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  6. // get the chart from session
  7. HttpSession session = request.getSession();
  8. BufferedImage chartImage = (BufferedImage) session.getAttribute("chartImage");
  9. // set the content type so the browser can see this as a picture
  10. response.setContentType("image/png");
  11. // send the picture
  12. PngEncoder encoder = new PngEncoder(chartImage, false, 0, 9);
  13. response.getOutputStream().write(encoder.pngEncode());
  14. }
  15. //Process the HTTP Post request
  16. publicvoid doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  17. doGet(request, response);
  18. }
  19. //Process the HTTP Put request
  20. publicvoid doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  21. }
  22. //Clean up resources
  23. publicvoid destroy() { }
  24. }



2. Create a servlet map in web.xml 

Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app>
  3. <servlet>
  4. <servlet-name>ChartViewer</servlet-name>
  5. <servlet-class>myapp.webwork.servlets.ChartViewer</servlet-class>
  6. </servlet>
  7. <servlet-mapping>
  8. <servlet-name>ChartViewer</servlet-name>
  9. <url-pattern>/servlet/ChartViewer</url-pattern>
  10. </servlet-mapping>
  11. </web-app>



3. Create a chart in a java bean (Pie3DDemo.java) 

Java代码 复制代码
  1. publicclass Pie3DDemo {
  2. private DefaultPieDataset getDataset() {
  3. // categories...
  4. String[] section = new String[] { "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" };
  5. // data...
  6. double[] data = newdouble[section.length];
  7. for (int i = 0; i < data.length; i++) {
  8. data[i] = 10 + (Math.random() * 10);
  9. }
  10. // create the dataset...
  11. DefaultPieDataset dataset = new DefaultPieDataset();
  12. for (int i = 0; i < data.length; i++) {
  13. dataset.setValue(section[i], data[i]);
  14. }
  15. return dataset;
  16. }
  17. public String getChartViewer(HttpServletRequest request, HttpServletResponse response) {
  18. DefaultPieDataset dataset = getDataset();
  19. // create the chart...
  20. JFreeChart chart = ChartFactory.createPie3DChart(
  21. "Pie3D Chart Demo", // chart title
  22. dataset, // data
  23. true, // include legend
  24. true,
  25. false
  26. );
  27. // set the background color for the chart...
  28. chart.setBackgroundPaint(Color.cyan);
  29. PiePlot plot = (PiePlot) chart.getPlot();
  30. plot.setNoDataMessage("No data available");
  31. // set drilldown capability...
  32. plot.setURLGenerator(new StandardPieURLGenerator("Bar3DDemo.jsp","section"));
  33. plot.setLabelGenerator(null);
  34. // OPTIONAL CUSTOMISATION COMPLETED.
  35. ChartRenderingInfo info = null;
  36. HttpSession session = request.getSession();
  37. try {
  38. //Create RenderingInfo object
  39. response.setContentType("text/html");
  40. info = new ChartRenderingInfo(new StandardEntityCollection());
  41. BufferedImage chartImage = chart.createBufferedImage(640, 400, info);
  42. // putting chart as BufferedImage in session,
  43. // thus making it available for the image reading action Action.
  44. session.setAttribute("chartImage", chartImage);
  45. PrintWriter writer = new PrintWriter(response.getWriter());
  46. ChartUtilities.writeImageMap(writer, "imageMap", info);
  47. writer.flush();
  48. } catch (Exception e) { }
  49. String pathInfo = "http://";
  50. pathInfo += request.getServerName();
  51. int port = request.getServerPort();
  52. pathInfo += ":"+String.valueOf(port);
  53. pathInfo += request.getContextPath();
  54. String chartViewer = pathInfo + "/servlet/ChartViewer";
  55. return chartViewer;
  56. }



6. 页面 

Java代码 复制代码
  1. <html>
  2. <head>
  3. <title>Pie Chart Demo</title>
  4. </head>
  5. <jsp:useBeanid="myChart"scope="session"class="myapp.webwork.beans.Pie3DDemo" />
  6. <body>
  7. <h2>Pie Chart Demo</h2>
  8. <%String chartViewer = myChart.getChartViewer(request, response);%>
  9. <img src="<%=chartViewer%>" border=0 usemap="#imageMap">
  10. </body>
  11. </html>



4)采用工具类ChartUtil和DisplayChart(jfreechart的servlet)输出
我用了上面的几个方法输出图片,发现页面里只能输出一个图片, 
不过下面的方法可以输出多个图片,而且是几种方式中最简单的一个,推荐使用。 

这种方式和上面的三种比较类似,是将javabean里的生成图片的方法写的一个工具类ChartUtil里面。 

1 .添加工具类ChartUtil 
public class ChartUtil { 
//  产生时间序列图,返回图片名称 

Java代码 复制代码
  1. publicstatic String generatePieChart(DefaultPieDataset dataset,String title,int width,int height,HttpSession session, PrintWriter pw) {
  2. String filename = null;
  3. try {
  4. if (session != null)
  5. {
  6. ChartDeleter deleter = (ChartDeleter)session.getAttribute("JFreeChart_Deleter");
  7. session.removeAttribute("JFreeChart_Deleter");
  8. session.setAttribute("JFreeChart_Deleter", deleter);
  9. }
  10. JFreeChart chart = ChartFactory.createPieChart3D(
  11. title, // chart title
  12. dataset, // data
  13. true, // include legend
  14. true,
  15. false );
  16. //  Write the chart image to the temporary directory
  17. ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
  18. //If the last parameter is null, the chart is a "one time"-chart and will be deleted after the first serving.
  19. //If the last parameter is a session object, the chart remains until session time out.
  20. filename = ServletUtilities.saveChartAsPNG(chart, width, height, info, session);
  21. //  Write the image map to the PrintWriter
  22. ChartUtilities.writeImageMap(pw, filename, info,true);
  23. pw.flush();
  24. } catch (Exception e) {
  25. System.out.println("Exception - " + e.toString());
  26. e.printStackTrace(System.out);
  27. filename = "picture_error.png"; }
  28. return filename;
  29. }
  30. }




2、在action里统计数据,设置好数据集dataset。传到页面 

3、 在页面里取出 
DefaultPieDataset piedataset=(DefaultPieDataset)request.getAttribute("piedataset"); 
// 用ChartUtil工具类产生图片 

Java代码 复制代码
  1. String p = ChartUtil.generatePieChart(piedataset," 项目收支线图",500,300,null, new PrintWriter(out));
  2. String p1 = request.getContextPath() + "/servlet/DisplayChart?filename=" + p;


通过以下方式输出 

Java代码 复制代码
  1. <td><img src="<%= p1 %>" width=500 height=300 border=0 usemap="#<%= p %>"></td>



4、在web.xml中添加 

Java代码 复制代码
  1. <servlet>
  2. <servlet-name>DisplayChart</servlet-name>
  3. <servlet-class>org.jfree.chart.servlet.DisplayChart</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>DisplayChart</servlet-name>
  7. <url-pattern>/servlet/DisplayChart</url-pattern>
  8. </servlet-mapping>



5) ApplicationFrame 方式

Java代码 复制代码
  1. publicclass PieChartDemo1 extends ApplicationFrame {
  2. public PieChartDemo1(String title) {
  3. super(title);
  4. setContentPane(createDemoPanel());
  5. }
  6. privatestatic JFreeChart createChart(PieDataset dataset) {
  7. JFreeChart chart = ChartFactory.createPieChart(
  8. .......
  9. return chart;
  10. }
  11. publicstatic JPanel createDemoPanel() {
  12. JFreeChart chart = createChart(createDataset());
  13. returnnew ChartPanel(chart);
  14. }
  15. publicstaticvoid main(String[] args) {
  16. PieChartDemo1 demo = new PieChartDemo1("Pie Chart Demo 1");
  17. demo.pack();
  18. RefineryUtilities.centerFrameOnScreen(demo);
  19. demo.setVisible(true);
  20. }
  21. }



六. 可参考资料与网址

官方网站 

[url]http://www.jfree.org/jfreechart/index.html [/url] 

官方论坛 

http://www.jfree.org/phpBB2/index.php

API 文档 

[url]http://www.jfree.org/jfreechart/api/gjdoc/index.html [/url] 

中文API 

[url]http://blog.sina.com.cn/u/405da78d010000ap [/url] 
图片: