首页 > 其他分享 >使用 JFreeChart来创建基于web的图表

使用 JFreeChart来创建基于web的图表

时间:2023-06-15 18:34:06浏览次数:45  
标签:web 对象 chart dataset 图表 柱状图 JFreeChart



级别: 初级

刘冬  软件工程师, 珠海市创我科技发展有限公司

2003 年 9 月 08 日

WWW的发展使得基于因特网的应用程序不再局限于静态或者简单的动态内容提供。传统的一些以软件包形式发布应用程序例如报表系统等都在逐渐搬到因特网上。但是这两者之间有着天壤之别,虽然对于数据获取、业务处理等方面基本类似,但是最大的差别在于用户界面。为了能在web浏览器上显示要求用户界面使用HTML以及图片的方式来展现数据,而传统的一些利用操作系统本身的控件来开发的用户界面无法适应琳琅满目的客户端,因此在这里也变得无能为力。回到本文的题目上来,为了创建一个可以在web浏览器上查看到图表一般有两种做法:第一种就是使用applet利用java本身对图形的支持来显示一个图表;第二种就是直接在web服务器端生成好图表图片文件后发送给浏览器。第一种方式显然对于客户端要求太高,随着现在主流浏览器放弃对JAVA的支持后,这种方式只适合一些局域网的应用,而对于因特网的环境就显得不太适合。因此我们下面将介绍一个JAVA的图表引擎JFreeChart用来产生基于WEB的图表。

JFreeChart项目简介

JFreeChart是开放源代码站点SourceForge.net上的一个JAVA项目,它主要用来各种各样的图表,这些图表包括:饼图、柱状图(普通柱状图以及堆栈柱状图)、线图、区域图、分布图、混合图、甘特图以及一些仪表盘等等。这些不同式样的图表基本上可以满足目前的要求。为了减少篇幅本文主要介绍前面三种类型的图表,读者可以触类旁通去开发其他样式的图表。下面几个是JFreeChart产生的这三种类型图表的结果:


图1


 



图2


 



图3


 


上面的三个图都是表示四个季度的某个产品的销量信息。在继续下面小节之前必须先准备好开发环境,因为是基于WEB浏览器的图表展现,因此需要一个Servlet引擎或者是J2EE应用服务器(例如WebSphere,Tomcat等)。WEB环境的搭建就不累赘了,读者根据喜好自行安装。JFreeChart引擎本身需要到SourceForge.net上下载,地址如下:

JFreeChart主页: http://www.jfree.org/jfreechart/index.html JFreeChart下载页面: http://sourceforge.net/projects/jfreechart/


下载的时候需要注意的是必须下载两个文件:JFreeChart以及Jcommon。目前最新配套版本是:JFreeChart 0.9.11 Jcommon 0.8.6

这里有点笔者在开发中遇见的问题需要注意的是:在使用Eclipse开发的时候会报一个莫名其妙的错误,错误可能指向某个类文件的第一行。遇到这样的问题一般是因为没有把Jcommon的jar包设置到项目的类路径中的缘故。具体的原因不祥。

使用 JFreeChart来创建基于web的图表_柱状图

回页首



解读JFreeChart的源码结构

在开始使用JFreeChart之前我们有必要先大概了解一下JFreeChart本身的结构以及它所带一些例子程序,这样有助于我们下一步自行开发。下载JFreeChart包后已经带有非常丰富的例子,因为JFreeChart这个项目本身的使用文档非常少,因此学习它最好的办法就是学习它所带的例子源码。在包org.jfree.chart.demo中有几十个文件用于展示JFreeChart所能支持的所有图表的结果。如果你的JDK是比较新的情况下可能在运行这些例子时会有问题,现象如下:

java.lang.UnsatisfiedLinkError: initDDraw   at sun.awt.windows.Win32OffScreenSurfaceData.initDDraw(Native Method)   at sun.awt.windows.Win32OffScreenSurfaceData.<clinit<(Win32OffScreenSurfaceData.java:141)   at sun.awt.Win32GraphicsDevice.<clinit<(Win32GraphicsDevice.java:58)   at sun.awt.Win32GraphicsEnvironment.makeScreenDevice(Win32GraphicsEnvironment.java:168)   at sun.java2d.SunGraphicsEnvironment.getScreenDevices(SunGraphicsEnvironment.java:240)   at sun.awt.Win32GraphicsEnvironment.getDefaultScreenDevice(Win32GraphicsEnvironment.java:61)   at java.awt.Window.init(Window.java:224)   at java.awt.Window.<init<(Window.java:268)   at java.awt.Frame.<init<(Frame.java:398)   at javax.swing.JFrame.<init<(JFrame.java:198)   at org.jfree.chart.demo.JFreeChartDemo.<init<(JFreeChartDemo.java:148)   at org.jfree.chart.demo.JFreeChartDemo.main(JFreeChartDemo.java:285)  Exception in thread "main"  


这个错误是由于新版的Swing大量的使用了微软的DirectDraw的技术来提高画图的性能,而可能你的显卡在这时候会跟你闹点情绪或者显卡本身并不支持这样的一个技术。难道就没有办法了嘛?要解决这个问题也非常简单,我们可以屏蔽掉DirectDraw,不让Swing使用该技术就可以了。在运行这些代码时给虚拟机指定参数-Dsun.java2d.noddraw即可。

这时可能你又该纳闷了,不说是基于Web的图表嘛,怎么又扯到Swing上了?这是因为为了使开发者容易上手,无需配置任何运行环境,所以这些例子都是基于GUI方式的用于展现给开发者如果生成一个图表,我们要学习的也就是如何利用这个引擎生成图表而不是怎么来显示一个图表。当我们把生成的图表对象Export到一个图像文件即可在Web上发布。

下面我们来介绍JFreeChart中几个核心的对象类:

类名

类的作用以及简单描述

JFreeChart

图表对象,任何类型的图表的最终表现形式都是在该对象进行一些属性的定制。JFreeChart引擎本身提供了一个工厂类用于创建不同类型的图表对象

XXXXXDataset

数据集对象,用于提供显示图表所用的数据。根据不同类型的图表对应着很多类型的数据集对象类

XXXXXPlot

图表区域对象,基本上这个对象决定着什么样式的图表,创建该对象的时候需要Axis、Renderer以及数据集对象的支持

XXXXXAxis

用于处理图表的两个轴:纵轴和横轴

XXXXXRenderer

负责如何显示一个图表对象

XXXXXURLGenerator

用于生成Web图表中每个项目的鼠标点击链接

XXXXXToolTipGenerator

用于生成图象的帮助提示,不同类型图表对应不同类型的工具提示类

基本上我认为JFreeChart项目本身的类结构的设计并不是很好,首先在创建图表的时候用到了大量的工厂方法,这样做虽然可以简化创建图表对象的代码,但是对项目本身或者开发人员来讲自行扩展一种新的图表都仍然是一件很麻烦的事情;其次除图表对象本身外其余的类过于复杂,使用者必须去了解每个类型的图表对象应该对应哪些Axis、Plot、Renderer类,并且必须非常熟悉这些类的构造函数中每个参数的具体含义。这些问题都大大困扰很多初学者。不过,虽然存在很多问题,但是JFreeChart本身仍不失为一个非常优秀的图表引擎,况且项目本身也在逐渐的发展中。

在非常简略的介绍了JFreeChart本身的代码结构后,下面我们开始动手试验几个常用的图表并把他们放到web上。

使用 JFreeChart来创建基于web的图表_柱状图

回页首



使用JFreeChart生成各种样式的图表

限于篇幅的问题我们在这里只实现两种常用的图表,其他类型图表读者可以触类旁通。我们先给出柱状图的实现,饼图的实现再来跟柱状图进行比较。

1 柱状图

package lius.chart.demo;  import java.io.*;  import org.jfree.data.*;  import org.jfree.chart.*;  import org.jfree.chart.plot.*;  /**   * 该类用于演示最简单的柱状图生成   * @author Winter Lau   */  public class BarChartDemo {   public static void main(String[] args) throws IOException{    CategoryDataset dataset = getDataSet2();    JFreeChart chart = ChartFactory.createBarChart3D(         "水果产量图", // 图表标题         "水果", // 目录轴的显示标签         "产量", // 数值轴的显示标签         dataset, // 数据集         PlotOrientation.VERTICAL, // 图表方向:水平、垂直         true,  // 是否显示图例(对于简单的柱状图必须是false)         false,  // 是否生成工具         false  // 是否生成URL链接         );             FileOutputStream fos_jpg = null;    try {     fos_jpg = new FileOutputStream("D:\\fruit.jpg");     ChartUtilities.writeChartAsJPEG(fos_jpg,100,chart,400,300,null);    } finally {     try {      fos_jpg.close();     } catch (Exception e) {}    }   }   /**    * 获取一个演示用的简单数据集对象    * @return    */   private static CategoryDataset getDataSet() {    DefaultCategoryDataset dataset = new DefaultCategoryDataset();    dataset.addValue(100, null, "苹果");    dataset.addValue(200, null, "梨子");    dataset.addValue(300, null, "葡萄");    dataset.addValue(400, null, "香蕉");    dataset.addValue(500, null, "荔枝");    return dat


程序运行结束后生成的图片文件效果如下图所示:


图4


 


如果是使用简单的数据即使用getDataSet方法获取数据集时产生的图片文件如下:


图5


 


2 饼图

对于饼图而言,数据集的获取用的不是同一个数据集类,另外饼图不支持同一个类别的项目中还有子项目这样的数据。我们只给出创建饼图的代码,至于写图表到一个文件则与柱状图一致,无需重复。

package lius.chart.demo;  import java.io.*;  import org.jfree.data.*;  import org.jfree.chart.*;  /**   * 用于演示饼图的生成   * @author Winter Lau   */  public class PieChartDemo {   public static void main(String[] args) throws IOException{    DefaultPieDataset data = getDataSet();    JFreeChart chart = ChartFactory.createPie3DChart("水果产量图",  // 图表标题    data,     true, // 是否显示图例    false,    false    );    //写图表对象到文件,参照柱状图生成源码   }   /**    * 获取一个演示用的简单数据集对象    * @return    */   private static DefaultPieDataset getDataSet() {    DefaultPieDataset dataset = new DefaultPieDataset();    dataset.setValue("苹果",100);    dataset.setValue("梨子",200);    dataset.setValue("葡萄",300);    dataset.setValue("香蕉",400);    dataset.setValue("荔枝",500);    return dataset;   }  }  


生成的饼图文件效果如下:


图6


 



使用 JFreeChart来创建基于web的图表_柱状图

回页首



将生成的图表移到浏览器上

为了将生成的图表直接传给客户端浏览器,只需要将前面两个例子中的文件流换成是通过HttpServletResponse对象获取到的输出流,详细代码清单如下:

package lius.chart.demo;  import java.io.IOException;  import javax.servlet.*;  import javax.servlet.http.HttpServlet;  import org.jfree.data.*;  import org.jfree.chart.*;  /**   * 演示通过servlet直接输出图表   * @author Winter Lau   */  public class ChartDemoServlet extends HttpServlet {   public void service(ServletRequest req, ServletResponse res)    throws ServletException, IOException    {    res.setContentType("image/jpeg");    DefaultPieDataset data = getDataSet();    JFreeChart chart = ChartFactory.createPie3DChart("水果产量图",    data,    true,    false,    false    );          ChartUtilities.writeChartAsJPEG(res.getOutputStream(),     100,chart,400,300,null);   }   /**    * 获取一个演示用的简单数据集对象    * @return    */   private static DefaultPieDataset getDataSet() {    DefaultPieDataset dataset = new DefaultPieDataset();    dataset.setValue("苹果",100);    dataset.setValue("梨子",200);    dataset.setValue("葡萄",300);    dataset.setValue("香蕉",400);    dataset.setValue("荔枝",500);    return dataset;   }  }  


使用 JFreeChart来创建基于web的图表_柱状图

回页首



高级主题

很多情况我们不仅仅要求可以在浏览器上显示一个图表,我们更需要客户可以直接在图表上做一下交互的操作,例如获取信息提示,点击图表某个部分进行更详细信息的展示等等。例如前面生成的简单柱状图,用户需要在看到柱状图后点击某种水果例如是苹果即可看到各个地区苹果产量的情况。为此就要求该图形具有交互操作的功能。在HTML中为了让一个图像具有可交互的功能就必须给该图像定义一个Map对象。下表节选一段具有该功能的HTML代码

<MAP NAME="chartMap"<  <AREA SHAPE="RECT" COORDS="81,15,126,254" href="?series=0&category=100" title="100 = 7,048"    οnclick="javascript:clickChart('100');return false;"<  <AREA SHAPE="RECT" COORDS="143,27,188,255" href="?series=0&category=200" title="200 = 6,721"    οnclick="javascript: clickChart ('200');return false;"<  <AREA SHAPE="RECT" COORDS="205,54,250,255" href="?series=0&category=300" title="300 = 5,929"    οnclick="javascript: clickChart ('300');return false;"<  <AREA SHAPE="RECT" COORDS="267,85,312,255" href="?series=0&category=400" title="400 = 5,005"    οnclick="javascript: clickChart ('400');return false;"<  <AREA SHAPE="RECT" COORDS="329,17,374,255" href="?series=0&category=Diet" title="Diet = 7,017" οnclick="javascript:    clickChart ('Diet');return false;"<  </MAP<  


由此就产生了一个问题:如果根据一个图像来生成对应的MAP对象。我们回头看看刚才的代码,在创建一个图表对象时候有两个参数,我们举柱状图的例子来讲这两个参数就是ChartFactory. createBarChart3D方法中的最后两个参数,这两个参数的类型都是布尔值。这两个参数意思分别是:是否创建工具提示(tooltip)以及是否生成URL。这两个参数分别对应着MAP中一个AREA的title属性以及href属性。

可是我想知道的是怎么来产生这个MAP啊!哈哈,不要着急,JFreeChart已经帮我们做好生成MAP对象的功能。为了生成MAP对象就要引入另外一个对象:ChartRenderingInfo。因为JFreeChart没有直接的方法利用一个图表对象直接生成MAP数据,它需要一个中间对象来过渡,这个对象就是ChartRenderingInfo。下图是生成MAP数据的流程图:


图7


 


如上图所示,ChartUtilities类是整个流程的核心,它周围的对象都是一些例如数据对象或者是文件等。这个流程简单描述如下:首先创建一个ChartRenderingInfo对象并在调用ChartUtilities的writeChartAsJPEG时作为最后一个参数传递进去。调用该方法结束后将产生一个图像文件以及一个填充好MAP数据的ChartRenderingInfo对象,有了这个对象我们还是没有办法获取具体的MAP数据,我们还必须借助于ChartUtilities的writeImageMap方法来将ChartRenderingInfo对象读取出来,获取MAP数据的代码片断如下:

  PrintWriter w = null;    FileOutputStream fos_jpg = null;    FileOutputStream fos_cri = null;    try{     //根据不同类型的图表使用不同类,以下是针对饼图的操作     PiePlot plot = (PiePlot) chart.getPlot();     plot.setURLGenerator(new StandardPieURLGenerator(url));     //设置工具提示       plot.setToolTipGenerator(new StandardPieToolTipGenerator());     fos_jpg = new FileOutputStream(“d:\\fruit.jpg”);      ChartUtilities.writeChartAsJPEG(      fos_jpg,      100,      chart,      400,      300,      info);     fos_cri = new FileOutputStream(__d:\\fruit.map__);     w = new PrintWriter(fos_cri);     ChartUtilities.writeImageMap(w, __mapname__, info);     w.flush();    }finally{     try{      w.close();     }catch(Exception e){}      try{      fos_cri.close();     }catch(Exception e){}      try{      fos_jpg.close();     }catch(Exception e){}    }  


打开文件D:\fruit.map,文件的内容就是要写到页面上的MAP数据。把生成的图像文件以及MAP数据文件写到页面上即可完成热点图表的功能。至于怎么结合两者之间的关系例如图像的useMap属性值必须与MAP对象的名称结合起来,必须根据实际的应用情况进行相应的处理。笔者建议把二者通过标签库封装起来,图像文件的名称以及MAP对象的名称由标签库统一进行控制,这样可以保证二者的一致性。



参考资料



关于作者

使用 JFreeChart来创建基于web的图表_柱状图_05


使用 JFreeChart来创建基于web的图表_柱状图_06

刘冬,他已经不再叫凤梨罐头了。珠海市创我科技发展有限公司软件工程师,主要从事在J2EE平台上实现商业智能(BI)方面的开发。 

标签:web,对象,chart,dataset,图表,柱状图,JFreeChart
From: https://blog.51cto.com/u_16065168/6494008

相关文章

  • 小鹿线Web前端怎么样?
    现在web前端开发开发技术在不断地迭代更新,有很多从事前端开发的程序员在技术上会遇到瓶颈,这个时候小伙伴就应该通过不断的学习开发技术知识,来提升自身的开发技术水平,那小伙伴应该怎么来学习呢?1.梳理清楚知识体系框架学习前端开发技术,不管是入门还是进阶,一定都要有知识体系建设......
  • idea 配置 javaweb项目
    对于老的web项目,不是springboot,需要的配置一、git clone 项目 二、配置 projectstructure 这几个都要配置,当然有的项目点开默认有的话修改一下就行,没有就 的手动添加 project 这几个都填好填对 没有classes 就创建一个 modules libbraries 把WEB-INF......
  • AJAX实现基于WEB的文件上传的进度控制保存草稿
    AJAX实现基于WEB的文件上传的进度控制 作者:liuzuochen 1.引言2.代码实现2.1.服务器端代码2.1.1.文件上传状态类(FileUploadStatus)2.1.2.文件上传状态侦听类(FileUploadListener)2.1.3.后台服务类(BackGroundService)2.1.4.文件上传状态控制类(Bea......
  • web中使用POI的例子
    web中使用POI的例子struts1.x的例子,struts2.x可以参考自己修改1.action的写法 importjava.io.*;importjava.sql.*;importjava.util.ArrayList;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.......
  • c# WebUploader 分块上传
    ​ASP.NET上传文件用FileUpLoad就可以,但是对文件夹的操作却不能用FileUpLoad来实现。下面这个示例便是使用ASP.NET来实现上传文件夹并对文件夹进行压缩以及解压。ASP.NET页面设计:TextBox和Button按钮。​编辑TextBox中需要自己受到输入文件夹的路径(包含文件夹),通过Button实......
  • web基础与HTTP协议
    目录一、DNS二、域名三、web基础四、HTTP五、总结        摘要:简单叙述web基础,网页的概念,域名解析,域名结构,HTML超文本传输语言,cookie和session扩展 一、DNS1.DNS概念内网和外网无法通信,为了内网可以和外网通信,dns技术解决问题,可......
  • Web 前端框架市场统计
    根据  w3techs所做的统计1,有17.8%的网站没有使用javascript库。在使用js库的web网站中,Jquery占据了大部分,Bootstrap, React,Ajax, Vue,Angular排行如下:其他还有一些js库占据剩下的1%: 对于React,Angular,Vue的统计比较2如下:React占据所有已知使用js的网站......
  • WebRtc链接
    1.FEC原理及其实现https://blog.csdn.net/tonychan129/article/details/1205397262.webrtcQOS方法(汇总篇)https://blog.csdn.net/tonychan129/article/details/1205819013.WebRTC架构分析-WebRTC的线程模型https://blog.csdn.net/tonychan129/article/details/1255858034.WebR......
  • .net WebUploader 分块上传
    ​ 一、概述 所谓断点续传,其实只是指下载,也就是要从文件已经下载的地方开始继续下载。在以前版本的HTTP协议是不支持断点的,HTTP/1.1开始就支持了。一般断点下载时才用到Range和Content-Range实体头。HTTP协议本身不支持断点上传,需要自己实现。 二、Range  用于请求头......
  • Nginx支持web界面执行bash|python等系统命令和脚本
    ##关闭防火墙##(centos6)serviceiptablesstopchkconfigiptablesoff##(centos7)systemctlstopfirewalldsystemctldisablefirewalld#关闭selinuxsed-i's/SELINUX=enforcing/SELINUX=disabled/'/etc/selinux/configsetenforce0#已有epel源的跳过此步骤,直接安装......