之前已经实现了数据的采集,现在已经有了基本的数据,下一步就需要使用这些数据实现统计图的绘制了。这里使用Jfreechart实现这些统计图的绘制。首先看一下Jfreechart的基本用法,只有知道了它的基本用法才有可能实现对更为复杂的统计图的绘制。
这里主要使用了它的三种绘制方式,绘制饼图、折线图和柱状图
源代码地址:https://github.com/kdyzm/day74_jfreechartDemo
一、准备工作
首先去官网下载相关jar包:http://www.jfree.org/jfreechart/download.html
实际下载地址:http://sourceforge.net/projects/jfreechart/files/
这里我使用了1.0.14版本的。
解压jar包之后在lib目录下找到以下三个jar包添加到classpath:
然后就能进行下一步了。
二、饼状图的生成
1.定义统计图的标题
String title="各大公司Java EE AS 市场占有率调查";
2.创建数据源,JFreechart使用DefaultPieDataset对象封装所有需要统计的数据。
DefaultPieDataset dpd=new DefaultPieDataset();
dpd.setValue("IBM", 25);
dpd.setValue("Oracle", 25);
dpd.setValue("JBoss", 25);
dpd.setValue("用友", 25);
3.使用最简单的绘图方式创建JFreechart对象
JFreeChart chart=ChartFactory.createPieChart(title, dpd, true, false, false);
很明显参数1是标题,参数2是数据源,参数三是legend(图例),即是否显示图例,所谓图例就是对统计图中的不同部分加以说明的部分。
4.最后保存到文件
ChartUtilities.saveChartAsJPEG(new File("D://a.jpg"), chart, 800, 500);
使用ChartUtilities保存到文件,800是宽度,500是长度。
5.到D盘下查看生成的结果(a.jpg):
我们发现中文的部分全部变成乱码了。统计图中有三处乱码,这三处乱码应当分别给予解决,但是解决方法是一模一样的,那就是设置中文字体,在jfreechart中所有乱码都是没有设置好字引起的。
6.解决中文乱码
JFreechart中的统计图可以大致分为两部分,一部分是绘图区(plot),另一部分是非绘图区(有点废话),绘图区很明显就是图中的圆形盘子,而非绘图区就包括了title、legend等部分。
(1)解决绘图区乱码问题,首先获取绘图区对象,然后设置标签为中文字体即可。
PiePlot plot = (PiePlot)chart.getPlot();
plot.setLabelFont(new Font("宋体",Font.BOLD,15));
(2)非绘图区中文乱码问题
解决title中文乱码:
chart.getTitle().setFont(new Font("宋体", Font.BOLD, 30));
解决legend中文乱码
chart.getLegend().setItemFont(new Font("微软雅黑", Font.PLAIN, 15));
注意设置字体一定要在ChartUtilities.saveChartAsJPEG方法之前,否则肯定是没有效果的。
解决完成中文乱码问题之后效果:
虽然问题是解决了,但是要注意,一旦使用中文字体之后生成统计图的速度就会降低很多,这大概和程序需要获取系统字体有关系吧。
7.设置3D效果,设置3D效果非常简单只需要讲之前的createPieChart方法替换成为createPieChart3D方法即可。
当然这个效果比较难看,是因为没有设置透明度的问题,设置透明度
plot.setForegroundAlpha(0.7F);
这样就显得有立体效果了。
8.定制绘图区标签,绘图区标签只是显示了公司的名称,但是并没有将各个公司所占的份额和百分比显示出来,我们大多数还想知道总数是多少等等,这就需要我们定制标签了。
plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}/{1}/{2}/{3}"));
通过向StandardPieSectionLabelGenerator类的构造方法传入一个字符串,我们可以定制标签的内容,这里设置的{}参数只有四种:
{0},标签名称
{1},实际的数量
{2},占的百分比
{3},总的数量
如果超出了这个范围,则直接不给解析如果加上了{4},则直接打印{4}
9.其余效果
(1)设置图表区和绘图区背景,这个使用的不多
//设置图表区背景
chart.setBackgroundImage(ImageIO.read(new File("C:/Users/kdyzm/Pictures/IA.full.1795695.jpg")));
//设置绘图区背景
plot.setBackgroundImage(ImageIO.read(new File("C:/Users/kdyzm/Pictures/IA.full.1787513.jpg")));
(2)设置分裂效果
plot.setExplodePercent("IBM", 0.3D);
plot.setExplodePercent("Oracle", 0.1D);
10.完整代码
package com.kdyzm.test.pie; import java.awt.Font;
import java.io.File; import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.data.general.DefaultPieDataset; /**
* 测试饼状图的生成
* @author kdyzm
*
* 需要注意的一点就是为了解决中文乱码问题,一定要在将流写入文件之前设置字体。
*
*/
public class TestPie {
public static void main(String[] args) throws Exception {
String title="各大公司Java EE AS 市场占有率调查";
DefaultPieDataset dpd=new DefaultPieDataset();
dpd.setValue("IBM", 25);
dpd.setValue("Oracle", 25);
dpd.setValue("JBoss", 25);
dpd.setValue("用友", 25); //使用最简单的绘图方式
JFreeChart chart=ChartFactory.createPieChart3D(title, dpd, true, false, false);
//解决标题中文乱码问题
chart.getTitle().setFont(new Font("宋体", Font.BOLD, 30));
//解决底部bar中中文乱码问题
chart.getLegend().setItemFont(new Font("微软雅黑", Font.PLAIN, 15));
PiePlot plot = (PiePlot)chart.getPlot();
// plot.setExplodePercent("IBM", 0.3D);
// plot.setExplodePercent("Oracle", 0.1D);
plot.setLabelFont(new Font("宋体",Font.BOLD,15));
plot.setForegroundAlpha(0.3F);
plot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}/{1}/{2}/{3}"));
//绘图区
/**
* 这里设置的{}参数只有四种
* {0},标签名称
* {1},实际的数量
* {2},占的百分比
* {3},总的数量
* 如果超出了这个范围,则直接不给解析如果加上了{4},则直接打印{4}
*/
// //设置图表区背景
// chart.setBackgroundImage(ImageIO.read(new File("C:/Users/kdyzm/Pictures/IA.full.1795695.jpg")));
// //设置绘图区背景
// plot.setBackgroundImage(ImageIO.read(new File("C:/Users/kdyzm/Pictures/IA.full.1787513.jpg"))); //设置分裂效果
ChartUtilities.saveChartAsJPEG(new File("D://a.jpg"), chart, 800, 500);
//解决每个扇形区域中中文乱码问题
System.out.println("打印完成!");
}
}
三、柱状统计图的实现
有了之前的饼状图的实现,再学习柱状统计图的实现就简单了很多,虽然有很多地方不一样,但是解决思路却是有很多相似之处。
package com.kdyzm.test.bar; import java.awt.Font;
import java.io.File; import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset; /**
* 测试柱状图的生成
* @author kdyzm
*
*/
public class BarTest {
public static void main(String[] args) throws Exception {
//提供数据集合
DefaultCategoryDataset dataset=new DefaultCategoryDataset();
dataset.addValue(100,"IBM", "第一季度");
dataset.addValue(103,"Oracle", "第一季度");
dataset.addValue(1000,"JBoss", "第一季度");
dataset.addValue(208,"用友", "第一季度"); dataset.addValue(2477,"IBM", "第二季度");
dataset.addValue(2343,"Oracle", "第二季度");
dataset.addValue(987,"JBoss", "第二季度");
dataset.addValue(3473,"用友", "第二季度"); dataset.addValue(1890,"IBM", "第三季度");
dataset.addValue(2980,"Oracle", "第三季度");
dataset.addValue(3889,"JBoss", "第三季度");
dataset.addValue(2890,"用友", "第三季度"); dataset.addValue(2347,"IBM", "第四季度");
dataset.addValue(1340,"Oracle", "第四季度");
dataset.addValue(2340,"JBoss", "第四季度");
dataset.addValue(3000,"用友", "第四季度"); //生成图表的进程
String title="一年之中各大公司Java EE AS销售统计";
JFreeChart chart=ChartFactory.createBarChart3D(title, "季度", "销量(万台)", dataset, PlotOrientation.VERTICAL, true, false, false); //集中解决中文乱码问题
chart.getTitle().setFont(new Font("微软雅黑", Font.BOLD, 30));
//设置底部bar中的字体样式
chart.getLegend().setItemFont(new Font("微软雅黑", Font.ITALIC, 20)); CategoryPlot categoryPlot=chart.getCategoryPlot();
//设置横坐标字体的样式
categoryPlot.getDomainAxis().setLabelFont(new Font("微软雅黑", Font.PLAIN, 15));
//设置横坐标小字体标题的样式
categoryPlot.getDomainAxis().setTickLabelFont(new Font("微软雅黑",Font.PLAIN,14)); //设置纵坐标标题的字体样式
categoryPlot.getRangeAxis().setLabelFont(new Font("微软雅黑",Font.PLAIN,15));
//设置前景色透明度
categoryPlot.setForegroundAlpha(0.7F); ChartUtilities.saveChartAsJPEG(new File("d:/bar.jpg"), chart, 800, 500);
System.out.println("图表生成完毕");
}
}
效果图:
代码说明:
和饼状统计图相比生成柱状统计图有几处不一样的地方
1.创建JFreechart对象对象使用的方法不一样了
JFreeChart chart=ChartFactory.createBarChart3D(title, "季度", "销量(万台)", dataset, PlotOrientation.VERTICAL, true, false, false);
这里季度是横坐标上的说明,销量(万台)是纵坐标上的说明,PlotOrientation.VERTICAL指定了绘图区的方向为垂直方向。
2.数据源的数据结果不相同,使用DefaultCategoryDataset类进行的数据封装。添加数据的方式变成了
dataset.addValue(100,"IBM", "第一季度");
第一个参数是数量,第二个参数是名称,第三个参数是“组号”,虽然API上给出的是“columnKey”,但是完全不明所以,从效果上来看确实是“组号”
3.解决中文乱码的地方需要改变。
非绘图区的title和legend解决乱码的方式不变,需要改变的是绘图区的乱码解决方式。在JFreechart中横坐标的名称叫做domain,做坐标的名称叫做range,通过CategoryPlot(其实也是Plot)获取横纵坐标对象从而设置字体是解决中文乱码的方式。
CategoryPlot categoryPlot=chart.getCategoryPlot();
//设置横坐标字体的样式
categoryPlot.getDomainAxis().setLabelFont(new Font("微软雅黑", Font.PLAIN, 15));
//设置横坐标小字体标题的样式
categoryPlot.getDomainAxis().setTickLabelFont(new Font("微软雅黑",Font.PLAIN,14)); //设置纵坐标标题的字体样式
categoryPlot.getRangeAxis().setLabelFont(new Font("微软雅黑",Font.PLAIN,15));
所谓小标题的字体样式指的就是"第一季度"、"第二季度"这样的"组标题"。
四、折线统计图的实现
折线统计图的实现和柱状统计图的实现几乎完全相同,只需要将创建柱状统计图的方法改变成为创建折线统计图的方法即可。
package com.kdyzm.test.bar; import java.awt.Font;
import java.io.File; import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset; /**
* 测试柱状图的生成
* @author kdyzm
*
*/
public class BarTest {
public static void main(String[] args) throws Exception {
//提供数据集合
DefaultCategoryDataset dataset=new DefaultCategoryDataset();
dataset.addValue(100,"IBM", "第一季度");
dataset.addValue(103,"Oracle", "第一季度");
dataset.addValue(1000,"JBoss", "第一季度");
dataset.addValue(208,"用友", "第一季度"); dataset.addValue(2477,"IBM", "第二季度");
dataset.addValue(2343,"Oracle", "第二季度");
dataset.addValue(987,"JBoss", "第二季度");
dataset.addValue(3473,"用友", "第二季度"); dataset.addValue(1890,"IBM", "第三季度");
dataset.addValue(2980,"Oracle", "第三季度");
dataset.addValue(3889,"JBoss", "第三季度");
dataset.addValue(2890,"用友", "第三季度"); dataset.addValue(2347,"IBM", "第四季度");
dataset.addValue(1340,"Oracle", "第四季度");
dataset.addValue(2340,"JBoss", "第四季度");
dataset.addValue(3000,"用友", "第四季度"); //生成图表的进程
String title="一年之中各大公司Java EE AS销售统计";
JFreeChart chart=ChartFactory.createLineChart(title, "季度", "销量(万台)", dataset, PlotOrientation.VERTICAL, true, false, false); //集中解决中文乱码问题
chart.getTitle().setFont(new Font("微软雅黑", Font.BOLD, 30));
//设置底部bar中的字体样式
chart.getLegend().setItemFont(new Font("微软雅黑", Font.ITALIC, 20)); CategoryPlot categoryPlot=chart.getCategoryPlot();
//设置横坐标字体的样式
categoryPlot.getDomainAxis().setLabelFont(new Font("微软雅黑", Font.PLAIN, 15));
//设置横坐标小字体标题的样式
categoryPlot.getDomainAxis().setTickLabelFont(new Font("微软雅黑",Font.PLAIN,14)); //设置纵坐标标题的字体样式
categoryPlot.getRangeAxis().setLabelFont(new Font("微软雅黑",Font.PLAIN,15)); ChartUtilities.saveChartAsJPEG(new File("d:/bar.jpg"), chart, 800, 500);
System.out.println("图表生成完毕");
}
}
效果图如下:
线条不够明显,解决方法就是加粗线条。
LineAndShapeRenderer renderer=(LineAndShapeRenderer) categoryPlot.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(3F));
renderer.setSeriesStroke(1, new BasicStroke(3F));
renderer.setSeriesStroke(2, new BasicStroke(3F));
renderer.setSeriesStroke(3, new BasicStroke(3F));
加粗线条之后的效果图:
试试3D效果:设置3D效果之后设置线条粗细就无效了。
JFreeChart chart=ChartFactory.createLineChart3D(title, "季度", "销量(万台)", dataset, PlotOrientation.VERTICAL, true, false, false);
这是设置了前景色透明度为0.8的效果。
categoryPlot.setForegroundAlpha(0.8F);
实现的完整代码:
package com.kdyzm.test.appline; import java.awt.BasicStroke;
import java.awt.Font;
import java.io.File; import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.category.DefaultCategoryDataset;
/**
* 折线图的生成方式和柱状图的生成方式几乎没有区别,但是最好设置一下线条的粗细,否则很难看
* @author kdyzm
*
*/
public class AppLine {
public static void main(String[] args) throws Exception {
//提供数据集合
DefaultCategoryDataset dataset=new DefaultCategoryDataset();
dataset.addValue(100,"IBM", "第一季度");
dataset.addValue(103,"Oracle", "第一季度");
dataset.addValue(1000,"JBoss", "第一季度");
dataset.addValue(208,"用友", "第一季度"); dataset.addValue(2477,"IBM", "第二季度");
dataset.addValue(2343,"Oracle", "第二季度");
dataset.addValue(987,"JBoss", "第二季度");
dataset.addValue(3473,"用友", "第二季度"); dataset.addValue(1890,"IBM", "第三季度");
dataset.addValue(2980,"Oracle", "第三季度");
dataset.addValue(3889,"JBoss", "第三季度");
dataset.addValue(2890,"用友", "第三季度"); dataset.addValue(2347,"IBM", "第四季度");
dataset.addValue(1340,"Oracle", "第四季度");
dataset.addValue(2340,"JBoss", "第四季度");
dataset.addValue(3000,"用友", "第四季度"); //生成图表的进程
String title="一年之中各大公司Java EE AS销售统计";
JFreeChart chart=ChartFactory.createLineChart3D(title, "季度", "销量(万台)", dataset, PlotOrientation.VERTICAL, true, false, false); //集中解决中文乱码问题
chart.getTitle().setFont(new Font("微软雅黑", Font.BOLD, 30));
//设置底部bar中的字体样式
chart.getLegend().setItemFont(new Font("微软雅黑", Font.ITALIC, 14));
CategoryPlot categoryPlot=chart.getCategoryPlot();
//设置横坐标字体的样式
categoryPlot.getDomainAxis().setLabelFont(new Font("微软雅黑", Font.PLAIN, 15));
//设置横坐标小字体标题的样式
categoryPlot.getDomainAxis().setTickLabelFont(new Font("微软雅黑",Font.PLAIN,14)); //设置纵坐标标题的字体样式
categoryPlot.getRangeAxis().setLabelFont(new Font("微软雅黑",Font.PLAIN,15));
//设置前景色透明度
categoryPlot.setForegroundAlpha(0.8F); //设置折线粗细
/*LineAndShapeRenderer renderer=(LineAndShapeRenderer) categoryPlot.getRenderer();
renderer.setSeriesStroke(0, new BasicStroke(3F));
renderer.setSeriesStroke(1, new BasicStroke(3F));
renderer.setSeriesStroke(2, new BasicStroke(3F));
renderer.setSeriesStroke(3, new BasicStroke(3F));*/ ChartUtilities.saveChartAsJPEG(new File("d:/appLine.jpg"), chart, 800, 500);
System.out.println("折线图表生成完毕");
}
}