生成基于浏览器的图表方式比较多。据我所知道的,常用的有三种:
1、
VML
方式实现。这种方式是通过产生客户端的代码,由客户端根据代码生成相应的图表。但这种方式产生的图表有很多的局限性,如受限于浏览器,有些浏览器可能并不支持
VML
。另外,没有封装完整的图表开发包。
2、
通过
applet
来产生图表。这种方式也对客户端要求比较高,必须要有
JRE
,而且通过
applet
生成的图表在加载过程中会有个
Java
的
Log
动画。用户看了可能会感觉不太舒服。
3、
通过服务端直接生成图表的图片。这种方式对客户端几乎没有什么要求,缺点是加重了服务端的负担,对服务端要求就相对高了点。
经过比较,根据项目自身特点,我们打算采用第三种方式来开发图表。为了缩短开发周期、节约成本,我们选用了开源的
JFreeChart
(
http://www.jfree.org/jfreechart/index.php
)
。
jfreechart
是一个免费创建图表的
java
工具,目前最新版本是
JFreeChart-1.0.0-rc1
。它可以生成各式各样的图表。这些图表包括饼图、柱状图、线形图、区域图、甘特图等等,基本可以满足各种项目的要求。但在开发过程中我也发现了
JFreeChart
的一些不足,或者说有些称得上是
BUG
。总体说来,
JFreeChart
还是个优秀的开源项目。
关于
JFreeChart
生成图表的文章比较多了,我主要谈谈使用
JFreeChart
的一些比较棘手问题以及解决方法。同时也会将问题所用到的源码(
JFreeChart-1.0.0-rc1+Struts1.2.4
)从项目中抽象出来一起提供给大家。
一、
图片上热点链接中文乱码的解决方法
这个问题是在我查阅关于
JFreeChart
相关资料时出现频率最高的一个问题。其实这个乱码问题不能怪罪于
JFreeChart
。有人甚至就因此认为
JFreeChart
对中文支持不太完善,
JFreeChart
可要叫了:我是冤枉的!
我们来找出问题产生的原因,这个问题也就不难解决了。
首先查看一下出现问题页面的
Html
源文件,你会发现在源文件的开头多出了一段
map
代码,代码类似于这样:
<map id="chart-30928.png" name="chart-30928.png">
<area shape="poly" coords="179,163,176,154,174,145" title="
洗衣机
=315(29.86%)" alt=""/>
…………
</map>
<html>
<head>
…………
|
这部分
map
代码其实是
JFreeChart
产生的,是用来产生图片上的热点链接,这也是问题产生的根源所在。你的
Jsp
页面通过
<%@ page contentType="text/html; charset=UTF-8" %>
或者
<%@ page contentType="text/html; charset=GBK" %>
来设置
contentType
这无可厚非,但
map
并不是由这个
jsp
页面产生的。它是
JFreeChart
通过
PrintWriter
产生的。查看一下你生成图片的
Chart
源码,其中有
ChartUtilities.writeImageMap(pw, filename, info, false)
这样的语句。这是用来向页面写入
map
代码的。默认情况下,
map
代码会以服务器默认编码
(ISO-8859-1)
输出。这就和你的
Jsp
编码不一致,从而产生乱码。
原因找到了,问题也就不难解决的。设置
PrintWriter
的
contentType
与
Jsp
的
contentType
保存一致就可以了。代码如下(笔者的
Web
应用是基于
Struts
框架的):
//PieMothAciton.java
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
//
设置输出编码格式
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
…………
String filename = chart.generatePieChart3D("
月统计比例图
",
session, out);
String graphURL = request.getContextPath()
+ "/servlet/DisplayChart?filename=" + filename;
request.setAttribute("filename",filename);
request.setAttribute("graphURL",graphURL);
return mapping.findForward(SUCCESS);
}
|
重新部署你的
Web
应用,中文乱码文件就可以解决了。
二、
饼图显示百分比
在饼图中
JFreeChart
默认只显示选项和数值,没有显示各项所占比例。由于手头没有
1.0
版的
JFreeChart Developer Guide
(这可是要钱的,后来想想即使有,也未必能找到关于百分比这方面的说明),再加上
DEMO
中的饼图都没有显示百分比,无法参考。后来在网上找到了一个老版本的例子,其中能显示百分比。它是通过在
PiePlot
中设置的:
PiePlot pie; pie.setPercentFormatString("#,###0.0#%");
|
但
1.0
版本中根本就找不到
setPercentFormatString
这方法,
JFreeChart
各版本之间改动比较大,很难兼容。还好它是开源的,把它的源码都搜索了一遍,认真读了一些源码,终于理出了头绪。
原来在
1.0.0-rc1
版中显示百分比已经调整到
StandardPieItemLabelGenerator
构造函数中了,
StandardPieItemLabelGenerator
有三个构造函数。
StandardPieItemLabelGenerator()
不显示各项所占比例。另外两个可以显示比例。代码如下:
plot.setLabelGenerator(new StandardPieItemLabelGenerator(StandardPieItemLabelGenerator.DEFAULT_TOOLTIP_FORMAT)); //
或者采用下面自定义样式显示,
{0}
表示选项,
{1}
表示数值,
{2}
表示所占比例
plot.setLegendLabelGenerator(new StandardPieItemLabelGenerator("{0}: ({1}M, {2})"));
|
效果如下图:
默认显示百分比是取整的,如果要让百分比保留二位小数,可以用第三个构造函数:
plot.setLabelGenerator(new StandardPieItemLabelGenerator(“{0}={1}({2})”,
NumberFormat.getNumberInstance(),
new DecimalFormat("0.00%")));
|
效果如下图:
三、
混合图表(不同类型的图混合显示)
我们经常用的是柱状图、曲线图、和饼图,这三类型图基本能满足大部分项目的需求。但有些项目比较特殊,可能需要在一张图上同时显示不同类型的图。这在
JFreeChart
中可以轻松实现。例如我们要做个流量监控的系统,该系统一天中在不同的时间段有不同的阀值(最大值),该阀值表示成阶梯线。而实际流量就是个曲线了。当流量在某个时段内超过阀值时就触发相应的事件(如限流)。要表示阀值和流量的对比关系就需要两种类型的图片在同一张图表上表示,如下图:
首先像创建普通图表一样来创建图片,笔者先创建了一个
XYStep Chart
。然后创建第二图表的
Renderer
,再分别将第二图表的
Dataset
、
Renderer
添加进第一图表的
plot
。实例代码如下:
//MultipleChart.java
JFreeChart jfreechart = ChartFactory.createXYStepAreaChart("
监控设置
",
"
时刻
",
"
流量
",
xydataset,
PlotOrientation.VERTICAL,
true,
true,
false);
XYPlot xyplot = jfreechart.getXYPlot();
…………
//
设置第二图表的
Renderer
StandardXYItemRenderer standardxyitemrenderer = new StandardXYItemRenderer();
standardxyitemrenderer.setToolTipGenerator(new StandardXYToolTipGenerator("{0}({1}) = {2}",
new SimpleDateFormat("HH:mm"),
new DecimalFormat("#,##0")));
//
将第二图表的
Dataset
、
Renderer
添加进
xyplot
xyplot.setDataset(1, lineDataset);
xyplot.setRenderer(1,standardxyitemrenderer);
|
这样就创建了曲线和阶梯的混合图表。
四、
其它问题
1)
版本问题。
JFreeChart
的各版本变动比较大,这在升级版本时是比较头疼的问题,升级时需要改动你代码的地方可能比较多。因此尽量采用最新的版本,新版本的文档可能比较少,但问题要相对少一些,在旧版中就出现过标注数值重叠在一起这样的问题。好的是
JFreeChart
是开源的,碰到解决不了的问题可以从源码中找到有参考价值的信息。
2)
设置背景透明度的
BUG
不知道这是不是
JFreeChart
的一个
BUG
。利用
chart.setBackgroundImageAlpha(0.5f)
来设置背景透明度,
ServletUtilities.saveChartAsPNG
保存图片。将
chart.setBackgroundImageAlpha(0.5f)
注释掉再生成图片,发现两张图片是一样的。也就是说
setBackgroundImageAlpha
方法无效,具体原因笔者还不太清楚,读者大家可以自己测试看看。