三、柱状图
【实例127】 用JFreeChart绘制柱状图
本例将实现在JSP页面中输出一个用户年龄阶段分布统计柱状图。
barChart.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.jfree.chart.JFreeChart,org.jfree.chart.ChartUtilities,
org.jfree.chart.ChartFactory,
org.jfree.chart.plot.PlotOrientation,
org.jfree.data.category.DefaultCategoryDataset"%>
<html>
<body>
<%
String dataName[]=new String[]{"0-30岁","30-50岁","50-70岁","70岁以上"};//显示数据系列
int dataValueCount[]={4,5,4,6};//数据系列对应的值
//------创建数据集,并设置值------
DefaultCategoryDataset categoryDataset = newDefaultCategoryDataset();
for(int i=0;i<dataName.length;i++)
categoryDataset.addValue(dataValueCount[i],dataName[i],dataName[i]);
String titleString="用户年龄阶段分布统计图";//图的标题
JFreeChart chart = ChartFactory.createBarChart(titleString,"用户年龄阶段","数量",
categoryDataset,PlotOrientation.VERTICAL,true,true,false);
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
%>
</body>
</html>
程序的运行结果如图17-4所示。
如果要绘制立体的柱状图,只须将程序中的语句:
JFreeChart chart = ChartFactory.createBarChart(titleString,"用户年龄阶段","数量",categoryDataset,PlotOrientation.VERTICAL,true,true,false);
修改为:
JFreeChart chart = ChartFactory.createBarChart3D(titleString,"用户年龄阶段","数量",categoryDataset,PlotOrientation.VERTICAL,true,true,false);
修改后,显示的立体柱状图如图17-5所示。
《JSP网络编程从实践到实践》原码下载地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575
在Web中开发图形显示功能,在一些管理信息系统是比较常用的。有些系统中使用调用office的ocx组件的方式来显示图形,这要求客户端必须要安装有office软件,那么有没有别的方法实现呢?JDK中带有图形开发的软件包AWT,然而,从事应用软件系统开发的程序员并非图形图像方面的专家,短时间内也无法掌握JDK中AWT的开发,需要了解的底层API也比较多。
百事通因此,可以考虑使用比较成熟的第三方的组件包来实现。
JFreeChart是一个开源的组件包,它提供了Java中常用统计图形的快速开发API,程序员只要掌握少量的接口就能绘制出漂亮的图形,而且这些图形不仅可用于带有客户端界面的Java应用程序中,也可以是在JSP, Servlet, Java Applet中。本章中将主要介绍在JSP中如何使用JFreeChart组件包开发常用的图形,如果要在Servlet、应用程序或Java Applet中实现类似的功能,可自行参考编程程序。
JFreeChart可用于创建饼图、线图、柱状图、散点图、甘特图等,本章将重点介绍常用的前三种图形的实现。可以从如下的网址得到许多有关于JFreeChart的信息:http://www.jfree.org/jfreechart/
本书使用的JFreeChart版本是1.0.1,可从如下的网址下载得到:
http://prdownloads.sourceforge.net/jfreechart/jfreechart-1.0.1.zip?download要在JSP中用JFreeChart开发Web图表,需要将JFreeChart的zip压缩包解压,在解压后的压缩包的lib子目录中,将gnujaxp.jar, jcommon-1.0.0.jar, jfreechart-1.0.1.jar三个jar包拷贝到Web应用的WEB-INF/lib目录下,即可在JSP中使用JFreeChart了。
一、 主要相关类介绍
JFreeChart组件包中的类相当之多,需要对图形越多的个性化设置或要开发越复杂的图形,就需要了解这些组件包中更多的类及其API。JFreeChart中常用有如下一些包:
org.jfree.chart:这个包包含了JFreeChart最为重要也是最为常用的几个类和接口,。
org.jfree.chart.data:数据集相关的接口和类。
org.jfree.chart.plot:绘图相关的类和接口。
org.jfree.chart.data.general:常用的数据集相关的接口和类。
还有许多其他的包,就不再一一介绍,有兴趣的读者可进一步参考JFreeChart的开发参考手册。
下面介绍开发中最为常用的几个类(或接口)。
(1)JFreeChart类
即org.jfree.chart.JFreeChart,这个类用于协调整个画图的处理过程。生成这个类通常使用ChartFactory类。JFreeChart主要的方法有以下几种。
draw()
方法原型如下:
public void draw(Graphics2D g2, Rectangle2D area)
此方法用于在图形设备上的特定区域画图。参数g2代码一个图形,参数area表示包容这个图形的矩形容器。Java中提供了几个图形设备:屏幕、打印机和图形缓冲区。JFreeChart绘图是由不同的Java.awt.Graphics2D包中的抽象类实现的,只有利用它们,JFreeChart才能向不同的图形设备输出图形。
(2)ChartFactory类
这个类是一个工厂类,即org.jfree.chart.ChartFactory,它提供了一些比较方便的创建图形对象的方法。此类常用的方法有以下几种。
createPieChart()
此方法用于创建一个标准的饼图。方法原型如下:
public static JFreeChart createPieChart(String title, PieDataset dataset, boolean legend, boolean tooltips, boolean urls)
其中,参数title为要创建的饼图的标题;参数dataset为创建饼图所使用的特定的数据集(可以为空);参数legend表示是否是一个图例;参数tooltips用于配置图形是否生成提示信息,参数urls配置图形是否生成URL。
createPieChart3D()
此方法用于创建一个标准的立体饼图。方法原型如下:
public static JFreeChart createPieChart3D(String title, PieDataset dataset, boolean legend, boolean tooltips, boolean urls)
方法参数的含义同createPieChart()方法。
createMultiplePieChart()
此方法用于创建一个饼图,以多张饼的形式显示。方法原型如下:
public static JFreeChart createMultiplePieChart(String title, CategoryDataset dataset, TableOrder order, boolean legend, boolean tooltips, boolean urls)
《JSP网络编程从实践到实践》原码下载地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575
其中,参数dataset为特定的用于创建饼图的分类数据集;参数order为数据被提取的先后顺序,是行优先可以使用常量TableOrder.BY_ROW;是列优先,则可设为TableOrder.BY _COLUMN;其他参数的含义同createPieChart()方法。
createMultiplePieChart3D ()
此方法用于创建一个立体的饼图,图形以多张饼的形式显示。方法原型如下:
public static JFreeChart createMultiplePieChart3D(String title, CategoryDataset dataset, TableOrder order, boolean legend, boolean tooltips, boolean urls)
createMultiplePieChart()
图形以多张饼的形式显示。方法原型如下:
public static JFreeChart createMultiplePieChart(String title, CategoryDataset dataset, TableOrder order, boolean legend,boolean tooltips, boolean urls)
createBarChart()
方法原型如下:
public static JFreeChart createBarChart(String title,String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset,PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls)
此方法用于根据dataset数据集生成条形图;参数categoryAxisLabel指定横向轴(分类轴)的提示字符串;参数valueAxisLabel指出竖向轴(值轴)的提示字符串,其他参数的含义同createPieChart()方法;参数orientation指出条形图是横向的还是竖向的,如果为竖向的其值可设为PlotOrientation.VERTICAL。
createBarChart3D
创建一个立体的条形图。方法原型如下:
public static JFreeChart createBarChart3D(String title,String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset,PlotOrientation orientation, boolean legend, boolean tooltips,boolean urls)
createLineChart()
方法原型如下:
public static JFreeChart createLineChart(String title,String categoryAxisLabel, String valueAxisLabel, CategoryDataset dataset,PlotOrientation orientation, boolean legend, boolean tooltips, boolean urls)
方法根据dataset数据集生成线图,其他参数的含义同createBarChart()方法。
(3)ChartUtilities类
即org.jfree.chart.ChartUtilities,通过ChartUtilities类可从chart对象生成PNG格式或JPEG格式的图片,也可生成带有单击范围的HTML图片(HTML image maps),这些生成图片的方法都是静态的(static)。
writeChartAsPNG()
JFreeChart通过一个开源的PNG格式图片的解码器来生成PNG图片。ChartUtilities类提供了一些方便使用的方法来直接通过输出流(OutputStream)生成图片。方法原型如下:
public static void writeChartAsPNG(OutputStream out, JFreeChart chart, int width, int height) throws IOException
其中,参数width为图形的宽度,参数heigth为图形的高度。
如果需要保存生成图片的相关参数信息(可用这此信息来生成HTML图片),可使用以下方法把图片的相关参数信息在创建图片时保存到一个ChartRenderingInfo对象中:
public static void writeChartAsPNG(OutputStream out, JFreeChart chart,int width, int height, ChartRenderingInfo info)
saveChartAsPN()
也可以把生成的PNG图片写入到一个文件中,方法原型如下:
public static void saveChartAsPNG(File file, JFreeChart chart, int width, int height)
《JSP网络编程从实践到实践》原码下载地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575
此方法的功能是将生成的PNG图片保存到参数file所指向的文件中。也可使用如下的方法在生成图片时保存图片的相关参数信息:
public staticvoidsaveChartAsPNG(Filefile,JFreeChartchart,intwidth,int height, ChartRenderingInfo info)
writeChartAsJPEG()
此方法用于生成JPEG格式的图片,方法原型有如下的两种:
public static void writeChartAsJPEG(OutputStream out, JFreeChart chart,int width, int height) throws IOException和
public static void writeChartAsJPEG(OutputStream out, JFreeChart chart, int width, int height, ChartRenderingInfo info)
参数的含义同writeChartAsPNG()方法。
saveChartAsJPEG()
此方法用于将生成的JPEG图片保存到文件中。方法原型有如下的两种:
public static void saveChartAsJPEG(File file, JFreeChart chart, int width, int height) 和
public static void saveChartAsJPEG(File file, JFreeChart chart, int width,int height, ChartRenderingInfo info)
writeImageMap()
这个方法用于生成对于HTML图片的单击范围描述,其实质是生成一段HTML代码,但调用这个方法前需要为生成的图形保存到ChartRenderingInfo对象中。方法原型如下:
public static void writeImageMap(PrintWriter writer, String name,String hrefPrefix, ChartRenderingInfo info)
(4)PlotOrientation类
即org.jfree.chart.plot.PlotOrientation,此类用于表示图形的显示方向,这个类主要有两个属性,分别用于表示图形显示的两个方向:横向和纵向。
PlotOrientation.HORIZONTAL:图形横向显示。
PlotOrientation.VERTICAL :图形纵向显示。
(5)DefaultCategoryDataset接口
即org.jfree.data.category.DefaultCategoryDataset,这是一个默认情况下使用的分类数据集接口。它的构造函数如下:
public DefaultCategoryDataset()
这个函数将生成一个空的数据集。也可以使用DatasetUtilities类的静态方法以数组作为参数来生成一个新的数据集,并用这个数组作为数据集中的数据。
addValue()
此方法用于向数据集中加入一个值。方法原型如下:
public addValue(Number value, Comparable rowKey, Comparable columnKey)
向数据集中增加值时,如果已经存在则会覆盖。
setValue()
方法原型如下:
public setValue(Number value, Comparable rowKey, Comparable columnKey)
此方法的功能同addValue()方法。
(6)DefaultPieDataset接口
即org.jfree.data.general.DefaultPieDataset,这是一个默认情况下使用的饼图数据集接口。
要新建一个饼图数据集,可使用这个接口的构造函数:
public DefaultPieDataset()
这个构造函数创建一个饼图数据集,并将数据集初始化为空。
getValue()
此方法得到数据集中指定的键对应的值,方法原型如下:
public Number getValue(Comparable key)
setValue()
此方法设置数据集中指定的键对应的值,方法原型如下:
public void setValue(Comparable key, Number value)
JFreeChart中还有许多的包和类,如果要开发出丰富多彩的图形,作一些个性化的设置,请参考JFreeChart的API手册。
《JSP网络编程从实践到实践》原码下载地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575
二、 饼图
【实例125】 用JFreeChart绘制饼图
本例将实现在JSP页面中输出一个用户年龄阶段分布统计饼图。
本章的所有实例都建立有Web应用webchart中,请事先将JFreeChart的jar包拷贝到WEB-INF/lib目录中。并在Tomcat 5.5的安装目录的conf子目录中作出虚拟目录配置,本章把此Web应用配置于虚拟目录webChart中。
pieChart.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.jfree.chart.JFreeChart,org.jfree.chart.ChartUtilities,
org.jfree.chart.ChartFactory,org.jfree.data.general.DefaultPieDataset"%>
<html>
<body>
<%
String dataName[]=new String[]{"0-30岁","30-50岁","50-70岁","70岁以上"};//显示数据系列
int dataValueCount[]={4,5,4,6};//数据系列对应的值
//------创建数据集,并设置值------
DefaultPieDataset pieDataset = new DefaultPieDataset();
for(int i=0;i<dataName.length;i++)
pieDataset.setValue(dataName[i],dataValueCount[i]);
String titleString="用户年龄阶段分布统计图";//图的标题
JFreeChart chart = ChartFactory.createPieChart(titleString,pieDataset,true,true, false);
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
%>
</body>
</html>
程序的运行结果如图17-1所示。
页面中只用了简单的几句Java程序就实现了饼图的输出。程序的基本流程是先设置饼图相关的数据集中的数据,再创建JFreeChart对象,最后用ChartUtilities来输出图形。对于上面的程序,只须把语句:
JFreeChart chart = ChartFactory.createPieChart(titleString,pieDataset,true,true, false);
修改为:
JFreeChart chart = ChartFactory.createPieChart3D(titleString,pieDataset,true, true,false);
即可实现立体图形的输出。如图17-2所示。
《JSP网络编程从实践到实践》原码下载地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575
【实例126】 从数据库中取出数据统计后再绘制饼图
pieChartDatabase.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.jfree.chart.JFreeChart,org.jfree.chart.ChartUtilities,
org.jfree.chart.ChartFactory,org.jfree.data.general.DefaultPieDataset,
java.sql.*"%>
<html><body>
<%
Connection con=null;//数据连接对象
Statement sql=null; //SQL语句对象
ResultSet rs=null;//结果记录集对象
String dataName[]=new String[]{"","","",""};//显示数据系列
int dataValueCount[]={0,0,0,0};//数据系列对应的值
//------加载驱动------
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
//------得到数据库连接------"
con=DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=testDatabase","sa","6599996");
sql=con.createStatement();
//------作数据查询,并得到结果记录集------
rs=sql.executeQuery("select '0-30岁' as userage,count(*) as usercount from userTable where user_age>=0 and user_age<30"
+" union select '30-50岁' as userage,count(*) as usercount from userTable where user_age>=30 and user_age<50"
+" union select '50-70岁' as userage,count(*) as usercount from userTable where user_age>=50 and user_age<70"
+" union select '70岁以上' as userage,count(*) as usercount from userTable where user_age>=70");
//------设置数据系列和其对应的值------
int j=0;
while(rs.next()){
dataName[j]=rs.getString("userage");
dataValueCount[j]=rs.getInt("usercount");
j++;
}
//------显示饼图------
DefaultPieDataset pieDataset = new DefaultPieDataset();
for(int i=0;i<dataName.length;i++)
pieDataset.setValue(dataName[i],dataValueCount[i]);
String titleString="用户年龄阶段分布统计图";//图的标题
JFreeChart chart = ChartFactory.createPieChart(titleString,pieDataset,true,true,false);
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
%>
</body></html>
程序中的SQL语句中使用是union语句,SQL语句如下:
select '0-30岁' as userage,count(*) as usercount from userTable where user_age>=0 and user_age<30 union select '30-50岁' as userage,count(*) as usercount from userTable where user_age>=30 and user_age<50 union select '50-70岁' as userage,count(*) as usercount from userTable where user_age>=50 and user_age<70 union select '70岁以上' as userage,count(*) as usercount from userTable where user_age>=70
语句较长,实现上述四个select子语句,再用union关键字把四个select子语句的结果记录集合并成一个结果记录集。
得到结果记录集后再遍历记录,将其设置为饼图的数据集,再显示饼图。程序的运行结果如图17-3所示。
在接下来的柱状图、线图实例中,如果数据源要取自数据库中,可参考本例来实现。
《JSP网络编程从实践到实践》原码下载地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575
四、线图
【实例128】 用JFreeChart绘制线图
本例将实现输出一个学生物理、化学及数学三门课程6次考试成绩的线图。
lineChart.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.jfree.chart.JFreeChart,org.jfree.chart.ChartUtilities,
org.jfree.chart.ChartFactory,
org.jfree.chart.plot.PlotOrientation,
org.jfree.data.category.DefaultCategoryDataset"%>
<html>
<body>
<%
//------数据线------
String dataLine1="物理";
String dataLine2="化学";
String dataLine3="数学";
//------数据列------
String dataCol1="1";
String dataCol2="2";
String dataCol3="3";
String dataCol4="4";
String dataCol5="5";
String dataCol6="6";
//------创建数据集,并设置值------
DefaultCategoryDataset categoryDataset = new DefaultCategoryDataset();
categoryDataset.addValue(60,dataLine1,dataCol1);
categoryDataset.addValue(70,dataLine1,dataCol2);
categoryDataset.addValue(83,dataLine1,dataCol3);
categoryDataset.addValue(90,dataLine1,dataCol4);
categoryDataset.addValue(92,dataLine1,dataCol5);
categoryDataset.addValue(85,dataLine1,dataCol6);
categoryDataset.addValue(63,dataLine2,dataCol1);
categoryDataset.addValue(45,dataLine2,dataCol2);
categoryDataset.addValue(67,dataLine2,dataCol3);
categoryDataset.addValue(76,dataLine2,dataCol4);
categoryDataset.addValue(90,dataLine2,dataCol5);
categoryDataset.addValue(87,dataLine2,dataCol6);
categoryDataset.addValue(50,dataLine3,dataCol1);
categoryDataset.addValue(76,dataLine3,dataCol2);
categoryDataset.addValue(84,dataLine3,dataCol3);
categoryDataset.addValue(96,dataLine3,dataCol4);
categoryDataset.addValue(88,dataLine3,dataCol5);
categoryDataset.addValue(80,dataLine3,dataCol6);
//------创建线图------
String titleString="XXXXXX学生成绩线图";//图的标题
JFreeChart chart =ChartFactory.createLineChart(titleString,"第几次考试","成绩",
categoryDataset,PlotOrientation.VERTICAL,true,true,false);
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,500,300);
%>
</body>
</html>
程序的运行结果如图17-6所示。
五、将图形导出成PDF文件
用JFreeChart生成的图形要导出成PDF文件,需要使用一个开源的iText软件包。本书使用iText1.4.3,可从如下的地址下载得到iText1.4.3:
http://www.lowagie.com/iText/download.html
如果要在当前Web应用中使用iText1.4.3,需要把itext-1.4.3.jar包拷贝到Web应用的WEB-INF/lib目录下。
《JSP网络编程从实践到实践》原码下载地址:http://shop.csai.cn/itbook/itbookinfo.asp?lbbh=10051575
【实例129】 将图形导出成PDF文件
本例实现的功能是将实例125中绘制的饼图输出到d:/newPDF.pdf文件。
pieChartAsPDF.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="org.jfree.chart.JFreeChart,org.jfree.chart.ChartUtilities,
org.jfree.chart.ChartFactory,org.jfree.data.general.DefaultPieDataset,
java.io.*,com.lowagie.text.pdf.*,com.lowagie.text.*,
java.awt.Graphics2D,java.awt.geom.Rectangle2D"%>
<html>
<body>
<%!
public void saveChartAsPDF(File file,JFreeChart chart,
int width,int height,FontMapper mapper) throws IOException{
//------保存图形为PDF文件------
OutputStream OPS=new BufferedOutputStream(new FileOutputStream(file));
writeChartAsPDF(OPS,chart,width,height,mapper);
OPS.close();
}
public void writeChartAsPDF(OutputStream OPS,JFreeChart chart,
int width,int height,FontMapper mapper){
//------把图片写入到PDF文件的输出流中------
Rectangle pagesize=new Rectangle(width,height);
Document document=new Document(pagesize,50,50,50,50);
try{
PdfWriter writer=PdfWriter.getInstance(document,OPS);
document.addAuthor("dengziyun");//文档作 者
document.addSubject("mypdf");//文档主题
document.open();
PdfContentByte cb=writer.getDirectContent();
PdfTemplate tp=cb.createTemplate(width,height);
Graphics2D g2=tp.createGraphics(width,height,mapper);
Rectangle2D r2d=new Rectangle2D.Double(0,0,width,height);
chart.draw(g2,r2d);
g2.dispose();
cb.addTemplate(tp,0,0);
}catch(Exception e){}
document.close();
}
%>
<%
String dataName[]=new String[]{"0-30岁","30-50岁","50-70岁","70岁以上"};//显示数据系列
int dataValueCount[]={4,5,4,6};//数据系列对应的值
//------创建数据集,并设置值------
DefaultPieDataset pieDataset = new DefaultPieDataset();
for(int i=0;i<dataName.length;i++)
pieDataset.setValue(dataName[i],dataValueCount[i]);
String titleString="用户年龄阶段分布统计图";//图的标题
JFreeChart chart = ChartFactory.createPieChart(titleString,pieDataset,true,true, false);
ChartUtilities.writeChartAsJPEG(response.getOutputStream(),chart,400,300);
File filePDF=new File("d:/newPDF.pdf");
saveChartAsPDF(filePDF,chart,400,300,new DefaultFontMapper());
%>
</body>
</html>
程序中声明了两个方法:saveChartAsPDF()和writeChartAsPDF(),前者用于实现将图片保存到文件中,后者用于将图片写入到PDF文件的输出流中。程序运行后生成了d:/newPDF.pdf文件,打开这个文件,如图17-8所示。
如果要查看PDF文件,需要安装Adobe Acrobat软件。