圆形柱状图,直接看代码(有详细注释)
BarChart3DCase.java
package com.graph.myself;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.io.File;
import java.text.DecimalFormat;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.ui.GradientPaintTransformType;
import org.jfree.ui.StandardGradientPaintTransformer;
import org.jfree.ui.TextAnchor;
import com.graph.myself.CylinderRenderer;
/**
* 3D直方图例子
* @author zengfantian
*
*/
public class BarChart3DCase {
/**
* 获取数据集
*
* @return CategoryDataset
*/
private CategoryDataset getDataSet() {
CategoryDataset dataset = new DefaultCategoryDataset();
// 同一种类型的数据放在一个数组元素中
final double[][] data = new double[][] {
{ 967, 1164, 1463, 1793, 1933 },
{ 2164, 3063, 3955, 4031, 6749 },
{ 1028, 1357, 1203, 1392, 2316 } };
// 横向说明
final String[] rowKeys = { "发明", "实用新型", "外观设计" };
// 横向坐标值
final String[] columnKeys = { "2006年", "2007年", "2008年", "2009年", "2010年" };
//用DatasetUtilities来构建所需要的数据对象
dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys,data);
return dataset;
}
/**
* 创建图表JfreeChart对象
* @param dataset 数据集
* @param title 图表标题
* @return 图表JFreeChart
*/
private JFreeChart createChart(CategoryDataset dataset,String title) {
//用ChartFactory来构建所需的Chart对象
JFreeChart chart = ChartFactory.createStackedBarChart3D(
title, //图表标题
"",//横向标签
"",//纵向标签
dataset, //数据集
PlotOrientation.VERTICAL, // 图表方向:水平、垂直,
true,//是否显示图例(对于简单的柱状图必须是false)
true, //
false //是否生成URL链接
);
chart = this.setChart(chart);
return chart;
}
/**
* 对X轴的设置
*
* @param domainAxis
*/
private void setXDomainAxis(CategoryAxis domainAxis) {
Font labelFont = new Font("宋体", Font.CENTER_BASELINE, 12);
domainAxis.setLowerMargin(0.1);// 设置距离图片左端距离此时为10%
domainAxis.setUpperMargin(0.1);// 设置距离图片右端距离此时为百分之10
domainAxis.setLabelFont(labelFont);// X轴标题
domainAxis.setTickLabelFont(labelFont);// X轴数值
domainAxis.setCategoryLabelPositionOffset(10);// 图表横轴与标签的距离(10像素)
domainAxis.setCategoryMargin(0.2);// 横轴标签之间的距离20%
// domainAxis.setMaximumCategoryLabelLines(1);
// domainAxis.setMaximumCategoryLabelWidthRatio(0);
domainAxis.setLabelFont(labelFont);// 轴标题
domainAxis.setTickLabelFont(labelFont);// 轴数值
// Lable(Math.PI/3.0)倾斜度
// domainAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 3.0));
domainAxis.setMaximumCategoryLabelWidthRatio(0.6f);// 横轴上的 Lable 是否完整显示
}
/**
* 对Y轴的设置
*
* @param ValueAxis
*/
private void setYDomainAxis(ValueAxis valueAxis) {
Font labelFont = new Font("宋体", Font.CENTER_BASELINE, 12);
valueAxis.setUpperMargin(0.1);// 设置最高的一个柱与图片顶端的距离(最高柱的10%)
valueAxis.setLowerMargin(0.15);// 设置最低的一个 Item 与图片底端的距离
valueAxis.setLabelFont(labelFont);// Y轴标题
valueAxis.setTickLabelFont(labelFont);// Y轴数值
// Lable水平显示
valueAxis.setLabelAngle(1.5);
}
/**
* 设置图表的颜色(渲染图表)
* 每根柱子的详细设置(三维设置)
*
* @param categoryPlot
*/
private void setRender(CategoryPlot plot) {
// BarRenderer3D renderer = new BarRenderer3D(); //柱状渲染器
CylinderRenderer renderer = new CylinderRenderer();//圆形渲染器
renderer.setGradientPaintTransformer(new StandardGradientPaintTransformer(GradientPaintTransformType.CENTER_HORIZONTAL));
renderer.setBaseOutlineStroke(new BasicStroke(0.3F));
renderer.setBaseToolTipGenerator(new StandardCategoryToolTipGenerator());
renderer.setBaseOutlinePaint(Color.red);// 边框颜色
renderer.setSeriesPaint(0, new Color(155, 151, 255));// 设置柱的颜色
renderer.setSeriesOutlinePaint(0, Color.BLACK);// 边框颜色
renderer.setSeriesPaint(1, new Color(159, 49, 94));// 设置柱的颜色
renderer.setSeriesOutlinePaint(0, Color.BLACK);// 边框颜色
renderer.setSeriesPaint(2, new Color(253, 255, 199));// 设置柱的颜色
renderer.setSeriesOutlinePaint(1, Color.red);// 边框为红色
renderer.setItemMargin(0.1);// 组内柱子间隔为组宽的10%
// 显示每个柱的数值,并修改该数值的字体属性
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
// 注意:此句很关键,若无此句,那数字的显示会被覆盖,给人数字没有显示出来的问题(3D的才需啊这句,2D的上面那句足矣)
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(
ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_CENTER));
renderer.setBaseItemLabelPaint(Color.BLUE);// 设置数值颜色,默认黑色
renderer.setIncludeBaseInRange(true);
renderer.setBaseItemLabelFont((new Font("黑体", Font.CENTER_BASELINE, 12)));// 12号黑体
renderer.setBaseItemLabelPaint(Color.black);// 字体为黑色
renderer.setBaseItemLabelsVisible(true);
// 设置柱子宽度
renderer.setMaximumBarWidth(0.05);
// 设置柱子高度
renderer.setMinimumBarLength(0.2);
// 设置柱子边框可见
// renderer.setDrawBarOutline(true);
// 使用我们设计的效果
plot.setRenderer(renderer);
}
/**
* 设置图表属性
* @param chart 需要设置的图表
* @return JFreeChart设置好的图表
*/
private JFreeChart setChart(JFreeChart chart){
//设置消除字体的锯齿渲染
//chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
// 设置Title和Legend的字体(不然会乱码)
chart.getTitle().setFont(new Font("宋体", Font.CENTER_BASELINE, 20));
chart.getLegend().setItemFont(new Font("宋体", Font.CENTER_BASELINE, 12));
// 获得图表区域对象
CategoryPlot plot = chart.getCategoryPlot();
//设置横虚线可见
plot.setRangeGridlinesVisible(true);
// 设置虚线色彩
plot.setRangeGridlinePaint(Color.gray);
// 设置柱图背景色
plot.setBackgroundPaint(Color.white);
// 设置纵横坐标的显示位置
plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
// 数据轴精度
NumberAxis vn = (NumberAxis) plot.getRangeAxis();
// 设置刻度必须从0开始
vn.setAutoRangeIncludesZero(true);
// 数据轴数据标签的显示格式
DecimalFormat df = new DecimalFormat("#0");
vn.setNumberFormatOverride(df);
// 设置图表的横轴(X轴)
CategoryAxis domainAxis = plot.getDomainAxis();
this.setXDomainAxis(domainAxis);
// 设置图表的纵轴(Y轴)
ValueAxis valueAxis = plot.getRangeAxis();
this.setYDomainAxis(valueAxis);
// 设置图表的颜色
this.setRender(plot);
return chart;
}
/**
* 将图表保存到指定的路径
* @param filePath 图片文件保存路径
* @param chart 需要保存的图表
* @param width 图片的宽度
* @param height 图片高度
*/
@SuppressWarnings("unused")
private void saveChartAsJPG(String filePath, JFreeChart chart, int width,int height) {
try {
File file = new File(filePath);
ChartUtilities.saveChartAsJPEG(file, chart, width, height);
System.out.println("图表已生成到:" + filePath);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
/**
* 在窗体中显示生成的图表
* @param chart 需要显示的图表
* @param frameTitle 窗体标题
*/
private void displayChart(JFreeChart chart,String frameTitle) {
// 将生成的报表放到预览窗口中
ChartFrame preview = new ChartFrame(frameTitle, chart);
preview.pack();
preview.setLocationRelativeTo(null);
preview.setVisible(true);
}
/**
* 测试函数
* @param args
*/
public static void main(String[] args) {
BarChart3DCase barChartcase = new BarChart3DCase();
CategoryDataset dataset = barChartcase.getDataSet();
JFreeChart chart = barChartcase.createChart(dataset,"“十一五”时期天津市三种类型专利授权量");
barChartcase.displayChart(chart,"“十一五”时期天津市三种类型专利授权量");
//barChartcase.saveChartAsJPG("C:/jfreechartdemo/s.jpg", chart, 400, 300);
}
}
CylinderRenderer.java(该类jfreechart的官方demo源码中有)
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space
package com.graph.myself;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.geom.*;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.CategoryItemEntity;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.labels.CategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer3D;
import org.jfree.chart.renderer.category.CategoryItemRendererState;
import org.jfree.chart.urls.CategoryURLGenerator;
import org.jfree.data.category.CategoryDataset;
import org.jfree.ui.GradientPaintTransformer;
public class CylinderRenderer extends BarRenderer3D
{
public CylinderRenderer()
{
}
public CylinderRenderer(double d, double d1)
{
super(d, d1);
}
public void drawItem(Graphics2D graphics2d, CategoryItemRendererState categoryitemrendererstate, Rectangle2D rectangle2d, CategoryPlot categoryplot, CategoryAxis categoryaxis, ValueAxis valueaxis, CategoryDataset categorydataset,
int i, int j, int k)
{
Number number = categorydataset.getValue(i, j);
if (number == null)
return;
double d = number.doubleValue();
java.awt.geom.Rectangle2D.Double double1 = new java.awt.geom.Rectangle2D.Double(rectangle2d.getX(), rectangle2d.getY() + getYOffset(), rectangle2d.getWidth() - getXOffset(), rectangle2d.getHeight() - getYOffset());
PlotOrientation plotorientation = categoryplot.getOrientation();
double d1 = calculateBarW0(categoryplot, plotorientation, double1, categoryaxis, categoryitemrendererstate, i, j);
double ad[] = calculateBarL0L1(d);
if (ad == null)
return;
org.jfree.ui.RectangleEdge rectangleedge = categoryplot.getRangeAxisEdge();
float f = (float)valueaxis.valueToJava2D(ad[0], double1, rectangleedge);
float f1 = (float)valueaxis.valueToJava2D(ad[1], double1, rectangleedge);
float f2 = Math.min(f, f1);
float f3 = Math.abs(f1 - f);
GeneralPath generalpath = new GeneralPath();
java.awt.geom.Ellipse2D.Double double2 = null;
if (plotorientation == PlotOrientation.HORIZONTAL)
{
generalpath.moveTo((float)((double)f2 + getXOffset() / 2D), (float)d1);
generalpath.lineTo((float)((double)(f2 + f3) + getXOffset() / 2D), (float)d1);
java.awt.geom.Arc2D.Double double3 = new java.awt.geom.Arc2D.Double(f2 + f3, d1, getXOffset(), categoryitemrendererstate.getBarWidth(), 90D, 180D, 0);
generalpath.append(double3, true);
generalpath.lineTo((float)((double)f2 + getXOffset() / 2D), (float)(d1 + categoryitemrendererstate.getBarWidth()));
double3 = new java.awt.geom.Arc2D.Double(f2, d1, getXOffset(), categoryitemrendererstate.getBarWidth(), 270D, -180D, 0);
generalpath.append(double3, true);
generalpath.closePath();
double2 = new java.awt.geom.Ellipse2D.Double(f2 + f3, d1, getXOffset(), categoryitemrendererstate.getBarWidth());
} else
{
generalpath.moveTo((float)d1, (float)((double)f2 - getYOffset() / 2D));
generalpath.lineTo((float)d1, (float)((double)(f2 + f3) - getYOffset() / 2D));
java.awt.geom.Arc2D.Double double4 = new java.awt.geom.Arc2D.Double(d1, (double)(f2 + f3) - getYOffset(), categoryitemrendererstate.getBarWidth(), getYOffset(), 180D, 180D, 0);
generalpath.append(double4, true);
generalpath.lineTo((float)(d1 + categoryitemrendererstate.getBarWidth()), (float)((double)f2 - getYOffset() / 2D));
double4 = new java.awt.geom.Arc2D.Double(d1, (double)f2 - getYOffset(), categoryitemrendererstate.getBarWidth(), getYOffset(), 0.0D, -180D, 0);
generalpath.append(double4, true);
generalpath.closePath();
double2 = new java.awt.geom.Ellipse2D.Double(d1, (double)f2 - getYOffset(), categoryitemrendererstate.getBarWidth(), getYOffset());
}
Object obj = getItemPaint(i, j);
if (getGradientPaintTransformer() != null && (obj instanceof GradientPaint))
{
GradientPaint gradientpaint = (GradientPaint)obj;
obj = getGradientPaintTransformer().transform(gradientpaint, generalpath);
}
graphics2d.setPaint(((java.awt.Paint) (obj)));
graphics2d.fill(generalpath);
if (obj instanceof GradientPaint)
graphics2d.setPaint(((GradientPaint)obj).getColor2());
if (double2 != null)
graphics2d.fill(double2);
if (isDrawBarOutline() && categoryitemrendererstate.getBarWidth() > 3D)
{
graphics2d.setStroke(getItemOutlineStroke(i, j));
graphics2d.setPaint(getItemOutlinePaint(i, j));
graphics2d.draw(generalpath);
if (double2 != null)
graphics2d.draw(double2);
}
org.jfree.chart.labels.CategoryItemLabelGenerator categoryitemlabelgenerator = getItemLabelGenerator(i, j);
if (categoryitemlabelgenerator != null && isItemLabelVisible(i, j))
drawItemLabel(graphics2d, categorydataset, i, j, categoryplot, categoryitemlabelgenerator, generalpath.getBounds2D(), d < 0.0D);
if (categoryitemrendererstate.getInfo() != null)
{
EntityCollection entitycollection = categoryitemrendererstate.getEntityCollection();
if (entitycollection != null)
{
String s = null;
CategoryToolTipGenerator categorytooltipgenerator = getToolTipGenerator(i, j);
if (categorytooltipgenerator != null)
s = categorytooltipgenerator.generateToolTip(categorydataset, i, j);
String s1 = null;
if (getItemURLGenerator(i, j) != null)
s1 = getItemURLGenerator(i, j).generateURL(categorydataset, i, j);
CategoryItemEntity categoryitementity = new CategoryItemEntity(generalpath.getBounds2D(), s, s1, categorydataset, categorydataset.getRowKey(i), categorydataset.getColumnKey(j));
entitycollection.add(categoryitementity);
}
}
}
}
效果图:
希望本文对研究JfreeChart圆柱状图的朋友们有帮助。(需要官方开发文档、官方demo源码或是对jfreeChart有兴趣的朋友可以留下邮箱,我会把我搜集的jfreeChart研究资料发送至邮箱)