jfreechart 饼状图和柱状图 自定义填充图片

来源:互联网 发布:申请软件著作权材料 编辑:程序博客网 时间:2024/05/17 10:52

最近项目生成报表中,用户要求生成的饼图和柱图都不用颜色区分,用纹理填充来区分。饼图要求随机一块 隔离 出来,特别显示,柱图要求用柱图和折线图联合比较。


后台生成图表选择的工具是jfreechart,个人感觉功能相当齐全,网上相关资料也很多。但填充图片网上是真的找不到类似案例。没办法,研究了一下jfreechart  API ,终于还是给发现了解决方法。


正文  柱图填充

先了解一下主要类及作用。JFreeChart类是通过ChartFactory(理解为生成chart的工厂)创建的类,代表图表。抽象类plot代表图表本身,包括背景,柱图,坐标轴,标题等等属性。基本上各个图有对应的PLOT类,饼图(pieplot)柱图(CategoryPlot)等。Render类,图表的渲染工具,类似画笔,用什么线条画,什么图片填充,同样的每个类有对应的render。(饼图没有)。柱图的render是BarRenderer,她有一个属性,BarPainter,即设置画笔画的内容


重写BarPainter。

import java.awt.Graphics2D;import java.awt.Paint;import java.awt.Stroke;import java.awt.geom.RectangularShape;import org.jfree.chart.renderer.category.BarPainter;import org.jfree.chart.renderer.category.BarRenderer;import org.jfree.ui.RectangleEdge;public class CustomeBarPainter implements BarPainter{@Overridepublic void paintBar(Graphics2D paramGraphics2D, BarRenderer paramBarRenderer, int paramInt1, int paramInt2,RectangularShape paramRectangularShape, RectangleEdge paramRectangleEdge) {// TODO Auto-generated method stub Paint itemPaint = paramBarRenderer.getItemPaint(paramInt1, paramInt2); paramGraphics2D.setPaint(itemPaint); paramGraphics2D.fill(paramRectangularShape); if (!(paramBarRenderer.isDrawBarOutline()))//柱状图加边框   从StandardBarPainter实现类copy return; Stroke stroke = paramBarRenderer.getItemOutlineStroke(paramInt1, paramInt2); Paint paint = paramBarRenderer.getItemOutlinePaint(paramInt1, paramInt2); if ((stroke != null) && (paint != null)) { paramGraphics2D.setStroke(stroke); paramGraphics2D.setPaint(paint); paramGraphics2D.draw(paramRectangularShape);  }}@Overridepublic void paintBarShadow(Graphics2D paramGraphics2D, BarRenderer paramBarRenderer, int paramInt1, int paramInt2,RectangularShape paramRectangularShape, RectangleEdge paramRectangleEdge, boolean paramBoolean) {// TODO Auto-generated method stubPaint itemPaint = paramBarRenderer.getItemPaint(paramInt1, paramInt2);paramGraphics2D.setPaint(itemPaint);paramGraphics2D.fill(paramRectangularShape);}}
设置柱图的barrender对象

if (dataset != null) {        plot.setDataset(1, dataset);//设置折线数据源        LineAndShapeRenderer lineandshaperenderer = new LineAndShapeRenderer(); //shape理解为数据点和线的渲染器        lineandshaperenderer.setSeriesPaint(0, new java.awt.Color(0, 0, 0));//设置线为黑色        plot.setRenderer(1, lineandshaperenderer);//渲染折线        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);//折线在柱状图前面显示}

BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());//柱子上顯示相關信息
        renderer.setMaximumBarWidth(0.075);// 设置柱子最大宽度        renderer.setBaseOutlinePaint(Color.BLACK);//设置柱子边框        renderer.setDrawBarOutline(true);        renderer.setBarPainter(new CustomeBarPainter());//自定义barPainter实现方法        renderer.setItemMargin(0);//設置不同種類柱子之間的距離               ValueAxis valueAxis = plot.getRangeAxis();        Axis axis = plot.getDomainAxis();        valueAxis.setLowerMargin(0);        valueAxis.setAxisLinePaint(Color.BLACK);//纵轴设置为黑        axis.setAxisLinePaint(Color.BLACK);//横轴设置为黑                String[] imageArray = new String[]{"16.png","17.png","4.png","15.png","3.png"};//填充纹理图片库        for (int i = 0,count = plot.getDataset().getRowCount(); i < count; i++) {        renderer.setSeriesPaint(i, getTexturePaint(imageArray[i%(imageArray.length)]));}//多柱子不同图片渲染
获取纹理填充图片


 /** * 获取填充图片 * */private static TexturePaint getTexturePaint(String fileName){        BufferedImage bi=null;        Rectangle r = null;        TexturePaint tp = null;        try {            InputStream in = ChartUtils.class.getClassLoader().getResourceAsStream("config/texture/"+fileName);            bi = ImageIO.read(in);        } catch (IOException e) {            e.printStackTrace();        }        r = new Rectangle(0,0,bi.getWidth(),bi.getHeight());        tp = new TexturePaint(bi,r);        return tp;    }

运行即可生成纹理填充的柱状图。


饼图的填充和柱图不一样,因为饼图没有对应的render方法。但是查看了pieplot的方法之后,发现setSectionPaint()方法。同样,把纹理图片获取成Paint对象即可。


 String[] imageArray = new String[]{"16.png","17.png","4.png","15.png","3.png"};        for (int i = 0,pieCount = piePlot.getDataset().getItemCount(); i < pieCount; i++) {        int j = i%imageArray.length;        piePlot.setSectionPaint(i,getTexturePaint(imageArray[j]));}

结果如下:






原创粉丝点击