- 浏览: 322103 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
chenfang_0913:
您好,我按照您的方法在Windows端进行了实现,可是我一直捕 ...
java实现网卡数据包抓取学习 -
wps886:
google了半天全是错的,只有楼主的xml配置有用,太感谢了 ...
奇怪的400 BAD REQUEST -
laputa73:
node.addEventListener('mouseup' ...
网络拓扑图DEMO -
njyyao:
单击、双击、右击的事件处理事件?
网络拓扑图DEMO -
lilinshtandby:
不错不错,赞一个
dhtmlxTree总结
|
级别: 初级
刘冬 (winter.lau@163.com), 软件工程师, 珠海市创我科技发展有限公司
2003 年 9 月 08 日
WWW的发展使得基于因特网的应用程序不再局限于静态或者简单的动态内容提供。传统的一些以软件包形式发布应用程序例如报表系统等都在逐渐搬到因特网上。但是这两者之间有着天壤之别,虽然对于数据获取、业务处理等方面基本类似,但是最大的差别在于用户界面。为了能在web浏览器上显示要求用户界面使用HTML以及图片的方式来展现数据,而传统的一些利用操作系统本身的控件来开发的用户界面无法适应琳琅满目的客户端,因此在这里也变得无能为力。回到本文的题目上来,为了创建一个可以在web浏览器上查看到图表一般有两种做法:第一种就是使用applet利用java本身对图形的支持来显示一个图表;第二种就是直接在web服务器端生成好图表图片文件后发送给浏览器。第一种方式显然对于客户端要求太高,随着现在主流浏览器放弃对JAVA的支持后,这种方式只适合一些局域网的应用,而对于因特网的环境就显得不太适合。因此我们下面将介绍一个JAVA的图表引擎JFreeChart用来产生基于WEB的图表。
JFreeChart是开放源代码站点SourceForge.net上的一个JAVA项目,它主要用来各种各样的图表,这些图表包括:饼图、柱状图(普通柱状图以及堆栈柱状图)、线图、区域图、分布图、混合图、甘特图以及一些仪表盘等等。这些不同式样的图表基本上可以满足目前的要求。为了减少篇幅本文主要介绍前面三种类型的图表,读者可以触类旁通去开发其他样式的图表。下面几个是JFreeChart产生的这三种类型图表的结果:
上面的三个图都是表示四个季度的某个产品的销量信息。在继续下面小节之前必须先准备好开发环境,因为是基于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之前我们有必要先大概了解一下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上。
|
限于篇幅的问题我们在这里只实现两种常用的图表,其他类型图表读者可以触类旁通。我们先给出柱状图的实现,饼图的实现再来跟柱状图进行比较。
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 dataset; } /** * 获取一个演示用的组合数据集对象 * @return */ private static CategoryDataset getDataSet2() { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(100, "北京", "苹果"); dataset.addValue(100, "上海", "苹果"); dataset.addValue(100, "广州", "苹果"); dataset.addValue(200, "北京", "梨子"); dataset.addValue(200, "上海", "梨子"); dataset.addValue(200, "广州", "梨子"); dataset.addValue(300, "北京", "葡萄"); dataset.addValue(300, "上海", "葡萄"); dataset.addValue(300, "广州", "葡萄"); dataset.addValue(400, "北京", "香蕉"); dataset.addValue(400, "上海", "香蕉"); dataset.addValue(400, "广州", "香蕉"); dataset.addValue(500, "北京", "荔枝"); dataset.addValue(500, "上海", "荔枝"); dataset.addValue(500, "广州", "荔枝"); return dataset; } } |
程序运行结束后生成的图片文件效果如下图所示:
如果是使用简单的数据即使用getDataSet方法获取数据集时产生的图片文件如下:
对于饼图而言,数据集的获取用的不是同一个数据集类,另外饼图不支持同一个类别的项目中还有子项目这样的数据。我们只给出创建饼图的代码,至于写图表到一个文件则与柱状图一致,无需重复。
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; } } |
生成的饼图文件效果如下:
|
为了将生成的图表直接传给客户端浏览器,只需要将前面两个例子中的文件流换成是通过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; } } |
|
很多情况我们不仅仅要求可以在浏览器上显示一个图表,我们更需要客户可以直接在图表上做一下交互的操作,例如获取信息提示,点击图表某个部分进行更详细信息的展示等等。例如前面生成的简单柱状图,用户需要在看到柱状图后点击某种水果例如是苹果即可看到各个地区苹果产量的情况。为此就要求该图形具有交互操作的功能。在HTML中为了让一个图像具有可交互的功能就必须给该图像定义一个Map对象。下表节选一段具有该功能的HTML代码
<MAP NAME="chartMap"> <AREA SHAPE="RECT" COORDS="81,15,126,254" href="?series=0&category=100" title="100 = 7,048" onclick="javascript:clickChart('100');return false;"> <AREA SHAPE="RECT" COORDS="143,27,188,255" href="?series=0&category=200" title="200 = 6,721" onclick="javascript: clickChart ('200');return false;"> <AREA SHAPE="RECT" COORDS="205,54,250,255" href="?series=0&category=300" title="300 = 5,929" onclick="javascript: clickChart ('300');return false;"> <AREA SHAPE="RECT" COORDS="267,85,312,255" href="?series=0&category=400" title="400 = 5,005" onclick="javascript: clickChart ('400');return false;"> <AREA SHAPE="RECT" COORDS="329,17,374,255" href="?series=0&category=Diet" title="Diet = 7,017" onclick="javascript: clickChart ('Diet');return false;"> </MAP> |
由此就产生了一个问题:如果根据一个图像来生成对应的MAP对象。我们回头看看刚才的代码,在创建一个图表对象时候有两个参数,我们举柱状图的例子来讲这两个参数就是ChartFactory. createBarChart3D方法中的最后两个参数,这两个参数的类型都是布尔值。这两个参数意思分别是:是否创建工具提示(tooltip)以及是否生成URL。这两个参数分别对应着MAP中一个AREA的title属性以及href属性。
可是我想知道的是怎么来产生这个MAP啊!哈哈,不要着急,JFreeChart已经帮我们做好生成MAP对象的功能。为了生成MAP对象就要引入另外一个对象:ChartRenderingInfo。因为JFreeChart没有直接的方法利用一个图表对象直接生成MAP数据,它需要一个中间对象来过渡,这个对象就是ChartRenderingInfo。下图是生成MAP数据的流程图:
如上图所示,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对象的名称由标签库统一进行控制,这样可以保证二者的一致性。
| 刘冬,他已经不再叫凤梨罐头了。珠海市创我科技发展有限公司软件工程师,主要从事在J2EE平台上实现商业智能(BI)方面的开发。 |
发表评论
-
禁止页面放大缩小
2013-05-12 18:42 1863<html> <head> &l ... -
在web.xml中添加多个filter
2011-05-10 15:32 6600web.xml中的多个filter的运行顺序walker(wa ... -
tomcat无法启动
2011-05-08 09:11 1082Myeclipse8.5 + Tomcat7.0.5 发布应 ... -
XML to JSON
2011-04-06 16:17 1265现在JSON在前台的应用越来越广泛,不过也有很多系统是基于XM ... -
ajax tree框架(zTree)
2011-04-05 12:23 2854在以往的项目中,有时会用到树菜单的操作.我用过dhtmltre ... -
通过HttpClient发送Web Service请求
2011-01-19 10:29 1811import java.io.ByteArrayInputSt ... -
使用JES搭建小巧的Mail服务器
2010-10-26 21:56 1542最新需要使用MAIL服务器进行测试,正所谓山不在高,有仙则灵. ... -
struts2+spring2+hibernate3所需要的最少jar包
2010-04-19 16:06 1568Spring2所需要的jar包最简单,只需要一个综合的spri ... -
Struts2中获取requset,session,application
2010-01-04 13:24 1587struts2中Action是集成于com.opensymph ... -
struts2.0中struts.xml配置文件详解(转)
2010-01-04 11:10 1089<!DOCTYPE struts PUBLIC &quo ... -
struts2-Unable to load configuration. - bean - jar
2010-01-01 12:01 2819在整合Struts2 + Spring2 + Hibernat ... -
[转载]企业级SOA之路——在Web Service中使用HTTP和JMS
2009-12-28 10:28 1178本文来自CSDN博客,转载请标明出处:http://blog. ... -
XAMPP虚拟主机配置,实现单主机多个站点
2009-10-24 23:31 2748打开注释 NameVirtualHost *:80 ... -
thinkphp中使用ajax接收json数据
2009-04-01 17:25 9439参考thinkphp+jquery实现ajax,扩展了下,写了 ... -
基于服务器推的web im(未实现)
2009-03-24 16:10 1353想着手研究一下服务器推技术,看看能不能写出一个web im程序 ... -
使用dhtmltree动态生成树菜单总结
2009-03-19 13:49 5708我之前发布的dhtmltree总 ... -
能够自由拖动布局区域的网页
2009-03-11 09:54 2465<html> <head> <t ... -
jquery+json小例子
2009-02-19 16:08 9972由有不当之处,还望大家能指出。 直接进入主题,使用jquery ... -
在OpenFire的基础上安装JWChat 1.0
2009-02-12 17:57 0http://blog.csdn.net/simonhe197 ... -
JSON介绍
2008-12-11 12:18 1990JSON已经被广泛誉为浏览器中XML的替代品,它的目标仅仅是成 ...
相关推荐
使用JFreeChart来创建基于web的图表
使用 JFreeChart来创建基于web的图表_files
使用JFreeChart来创建基于web的图表.docx
本文档主要讲述的是使用 JFreeChart来创建基于web的图表;JFreeChart是开放源代码站点SourceForge.net上的一个JAVA项目,它主要用来各种各样的图表,这些图表包括:饼图、柱状图(普通柱状图以及堆栈柱状图)、线图、...
用JFreeChart创建基于Web的图表.pdf
传统的一些以软件包形式发布应用程序例如报表系统等都在逐渐搬到因特网上。但是这两者之间有着天壤之别,虽然对于数据获取、业务处理等方面...因此我们下面将介绍一个JAVA的图表引擎JFreeChart用来产生基于WEB的图表。
jfreechart-1.0.0-demo.jar jfreechart-1.0.0.zip JFreeChart-API.chm JFreeChart -- 柱状图.mht JfreeChart.doc JFreeChart0.9.16 ...使用 JFreeChart来创建基于web的图表_IBM.mht 使用JFreeChart创建图象http.mht
Sitemesh 是一个基于WEB页面的布局、装饰以及应用整合的开源框架。它能帮助我们在由大量页面构成的项目中创建一致的页面布局和外观,如一致的导航条,一致的 banner,一致的版权,等等。它不仅仅能处理动态的内容,...
WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...
WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...
6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...
WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...
WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...
WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...