圆形柱状图,直接看代码(有详细注释)
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研究资料发送至邮箱)