JfreeChart集萃


远去的渡口的JfreeChart集萃 作者: 远去的渡口 http://julianna-only.javaeye.com 我的JfreeChart精选 http://www.javaeye.com - 做最棒的软件开发交流社区 第 1 / 40 页 本书由JavaEye提供的电子书DIY功能自动生成于 2010-11-25 目 录 1. JfreeChart 1.1 JfreeChart折线图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2 JfreeChart 3D柱状图 带基准线的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16 1.3 JfreeChart 3D饼图总结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 1.4 JfreeChart 散点图,加了区域范围说明 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .25 1.5 JfreeChart热点map的应用 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 1.6 JfreeChart如何处理乱码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 http://julianna-only.javaeye.com 第 2 / 40 页 1.1 JfreeChart折线图 发表时间: 2009-05-22 在这个公司,用到了太多的JfreeChart,今天就对折线图作一个总结,希望对大家有点帮助,我这里直接是与业 务逻辑相关的,业务需要的数据加载到数据集等,不过我会作一些注释的,呵,之前有网友建议写注释。 折线图,大可分为两种, (1)X轴值类型为String的。 2)常用的是X轴值是日期的,并且,有时需要满足这样的需求: 1、时间要连续。 2、时间可以设置固定的跨度,比如,2009-02-01,2009-02-04,2009-02-07…… 3、由于时间跨度较大,想要做到不同精度的图表,如时间为10天时,以日(yyyy-MM-dd)格式为精度,时 间跨度为2个月时,以周(如2009年第3周)为精度,跨度为6个月时,以月(2009年8月)为精度. 下面,针对比较复杂的(2)来讲解: 1、取到业务逻辑需要的数据:(具体过程就不啰嗦了,就是查询数据库,得到想要的字段的值,加载到List里面) 返回List PressureBean的包含的属性: int userId; String bpDate; String bpTime; int syspress; //收缩压(mmHg) int diapress; //舒张压(mmHg) 2、加载数据集 public static TimeSeriesCollection createTimeSeries( List list, int dayOrweekOrmonth, Log log, String shou,String shu ) { TimeSeriesCollection timesers = new TimeSeriesCollection(); http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 3 / 40 页 int mon = 1; int day = 1; int ye = 2000; int week = 1; // 按天显示 if (dayOrweekOrmonth == 0) { TimeSeries timeseries = new TimeSeries(shou, org.jfree.data.time.Day.class); TimeSeries timeseries1 = new TimeSeries("c1", org.jfree.data.time.Day.class); TimeSeries timeseriedia = new TimeSeries(shu, org.jfree.data.time.Day.class); TimeSeries timeseriedia1 = new TimeSeries("d1", org.jfree.data.time.Day.class); Iterator it = list.iterator(); while (it.hasNext()) { PressureBean pres = it.next(); String date = pres.getBpDate(); ye = Integer.parseInt(date.substring(0, 4)); mon = Integer.parseInt(date.substring(5, 7)); day = Integer.parseInt(date.substring(8, date.length())); Day days = new Day(day, mon, ye); double sys = pres.getSyspress(); double dia = pres.getDiapress(); if (sys != -1 && sys > 0) { timeseries.add(days, sys); } else { timeseries1.add(days, null); } if (sys != -1 && sys > 0) { http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 4 / 40 页 timeseriedia.add(days, dia); } else { timeseriedia1.add(days, null); } } timesers.addSeries(timeseries); timesers.addSeries(timeseriedia); timesers.addSeries(timeseries1); timesers.addSeries(timeseriedia1); } else if (dayOrweekOrmonth == 1) {//按周显示 TimeSeries timeseries = new TimeSeries(shou, org.jfree.data.time.Week.class); TimeSeries timeseries1 = new TimeSeries("c1", org.jfree.data.time.Week.class); TimeSeries timeseriedia = new TimeSeries(shu, org.jfree.data.time.Week.class); TimeSeries timeseriedia1 = new TimeSeries("d1", org.jfree.data.time.Week.class); Iterator it = list.iterator(); while (it.hasNext()) { PressureBean pres = it.next(); String date = pres.getBpDate(); String[] spls = date.split("-"); if (spls.length == 2) { ye = Integer.parseInt(spls[0]); mon = Integer.parseInt(spls[1]); } else { log.error("the date of weeks is wrong"); } Week days = new Week(mon, ye); http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 5 / 40 页 double sys = pres.getSyspress(); double dia = pres.getDiapress(); if (sys != -1 && sys > 0) { timeseries.add(days, sys); } else { timeseries1.add(days, null); } if (sys != -1 && sys > 0) { timeseriedia.add(days, dia); } else { timeseriedia1.add(days, null); } } timesers.addSeries(timeseries); timesers.addSeries(timeseriedia); timesers.addSeries(timeseries1); timesers.addSeries(timeseriedia1); } else {//按月显示 TimeSeries timeseries = new TimeSeries(shou, org.jfree.data.time.Month.class); TimeSeries timeseries1 = new TimeSeries("c1", org.jfree.data.time.Month.class); TimeSeries timeseriedia = new TimeSeries(shu, org.jfree.data.time.Month.class); TimeSeries timeseriedia1 = new TimeSeries("s", org.jfree.data.time.Month.class); Iterator it = list.iterator(); while (it.hasNext()) { PressureBean pres = it.next(); String date = pres.getBpDate(); http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 6 / 40 页 String[] spls = date.split("-"); if (spls.length == 2) { ye = Integer.parseInt(spls[0]); mon = Integer.parseInt(spls[1]); } else { log.error("the date of weeks is wrong"); } Month days = new Month(mon, ye); double sys = pres.getSyspress(); double dia = pres.getDiapress(); if (sys != -1 && sys > 0) { timeseries.add(days, sys); } else { timeseries1.add(days, null); } if (sys != -1 && sys > 0) { timeseriedia.add(days, dia); } else { timeseriedia1.add(days, null); } } timesers.addSeries(timeseries); timesers.addSeries(timeseriedia); timesers.addSeries(timeseries1); timesers.addSeries(timeseriedia1); } return timesers; } http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 7 / 40 页 3、画折线图,两个数据集,收缩压和舒张压,并且,这两条曲线还各自包含一个区域范围,并不单单是一条基 准线,而是一个基准范围 private static JFreeChart createChartPress(XYDataset xydataset, int weekOrmonth, String title, String y, String index, String week, String year, int searchby, String month, String nodatamess, List list, Log log, String bp_shou, String bp_shuzhang) { // 有可能用户在后面的版本中故意输入不正常数值,但是为了保证图片画图的完整,这里先计算 // 用户血压值的最大值。 double maxpress = 0; double addmax = 50; double min = 40; if (list != null && list.size() > 0) { Iterator it = list.iterator(); while (it.hasNext()) { PressureBean pres = it.next(); double sys = pres.getSyspress(); double dia = pres.getDiapress(); if (maxpress < sys) { maxpress = sys; } if (maxpress < dia) maxpress = dia; if (min > sys) { min = sys; } http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 8 / 40 页 if (min > dia) min = dia; } maxpress += addmax; min -= 10; log.info("high press value is =" + maxpress); } if (xydataset != null) { int counts = xydataset.getItemCount(0); if (counts == 0) { xydataset = null; } } JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(title, "", y, xydataset, true, true, false); jfreechart.setBackgroundPaint(Color.white); // 设置标题的颜色 TextTitle text = new TextTitle(title); text.setPaint(new Color(102, 102, 102)); jfreechart.setTitle(text); XYPlot xyplot = jfreechart.getXYPlot(); xyplot.setBackgroundPaint(new Color(255, 253, 246)); xyplot.setOutlineStroke(new BasicStroke(1.5f)); // 边框粗细 ValueAxis vaxis = xyplot.getDomainAxis(); vaxis.setAxisLineStroke(new BasicStroke(1.5f)); // 坐标轴粗细 vaxis.setAxisLinePaint(new Color(215, 215, 215)); // 坐标轴颜色 xyplot.setOutlineStroke(new BasicStroke(1.5f)); // 边框粗细 http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 9 / 40 页 vaxis.setLabelPaint(new Color(10, 10, 10)); // 坐标轴标题颜色 vaxis.setTickLabelPaint(new Color(102, 102, 102)); // 坐标轴标尺值颜色 vaxis.setLowerMargin(0.06d);// 分类轴下(左)边距 vaxis.setUpperMargin(0.14d);// 分类轴下(右)边距,防止最后边的一个数据靠近了坐标轴。 //X轴为日期格式,这里是专门的处理日期的类, SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); DateAxis dateaxis = (DateAxis) xyplot.getDomainAxis(); if (weekOrmonth == 0) {//以天为刻度,时间格式为yyyy-MM-dd,如2008-02-06 dateaxis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, 1, format)); } else if (weekOrmonth == 1) {//以周为刻度,时间显示为 2009年第4周((这里是SimpleDateFormat的用法, //这里为了作繁体版,英文版和简体版,用了国际化处理,将这些可变的资源在文字资源里面,注意一下,这里的y,M、w是SimpleDateFormat的关键字, //如英文表示09年第3周就是09W3,那么,这里的W需要用‘’引起来) format = new SimpleDateFormat("yyyy" + year + index + "w" + week); dateaxis.setTickUnit(new DateTickUnit(DateTickUnit.DAY, 7, format)); } else if (weekOrmonth == 2) {//以月为刻度,时间显示为09-02 (09年2月) format = new SimpleDateFormat("yy-MM"); dateaxis .setTickUnit(new DateTickUnit(DateTickUnit.MONTH, 1, format)); } dateaxis.setVerticalTickLabels(false); // 设为true表示横坐标旋转到垂直。 if (searchby == 6 || searchby == 3) { dateaxis.setAutoTickUnitSelection(true); // 由于横轴标签过多,这里设置为自动格式 。 dateaxis.setDateFormatOverride(format); } dateaxis.setTickMarkPosition(DateTickMarkPosition.START); ValueAxis valueAxis = xyplot.getRangeAxis(); valueAxis.setUpperBound(maxpress); valueAxis.setAutoRangeMinimumSize(1); valueAxis.setLowerBound(min); valueAxis.setAutoRange(false); valueAxis.setAxisLineStroke(new BasicStroke(1.5f)); // 坐标轴粗细 valueAxis.setAxisLinePaint(new Color(215, 215, 215)); // 坐标轴颜色 valueAxis.setLabelPaint(new Color(10, 10, 10)); // 坐标轴标题颜色 http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 10 / 40 页 valueAxis.setTickLabelPaint(new Color(102, 102, 102)); // 坐标轴标尺值颜色 xyplot.setRangeGridlinesVisible(true); xyplot.setDomainGridlinesVisible(true); xyplot.setRangeGridlinePaint(Color.LIGHT_GRAY); xyplot.setDomainGridlinePaint(Color.LIGHT_GRAY); xyplot.setBackgroundPaint(new Color(255, 253, 246)); xyplot.setNoDataMessage(nodatamess);//没有数据时显示的文字说明。 xyplot.setNoDataMessageFont(new Font("", Font.BOLD, 14));//字体的大小,粗体。 xyplot.setNoDataMessagePaint(new Color(87, 149, 117));//字体颜色 xyplot.setAxisOffset(new RectangleInsets(0d, 0d, 0d, 5d)); // // add range marker(舒张压的区域marker,范围是从62到81) double lowpress = 62; double uperpress = 81; IntervalMarker intermarker = new IntervalMarker(lowpress, uperpress); intermarker.setPaint(Color.decode("#66FFCC"));// 域顏色 intermarker.setLabelFont(new Font("SansSerif", 41, 14)); intermarker.setLabelPaint(Color.RED); intermarker.setLabel(bp_shuzhang); if (xydataset != null) { xyplot.addRangeMarker(intermarker, Layer.BACKGROUND); } //(收缩压的区域marker,范围是从102到120) double lowpress1 = 102; double uperpress1 = 120; IntervalMarker inter = new IntervalMarker(lowpress1, uperpress1); inter.setLabelOffsetType(LengthAdjustmentType.EXPAND); inter.setPaint(Color.decode("#66FFCC"));// 域顏色 inter.setLabelFont(new Font("SansSerif", 41, 14)); inter.setLabelPaint(Color.RED); inter.setLabel(bp_shou); http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 11 / 40 页 if (xydataset != null) { xyplot.addRangeMarker(inter, Layer.BACKGROUND); // 加上Layer.BACKGROUND,将maker调到折线下面。 } XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyplot .getRenderer(); //第一条折线的颜色 xylineandshaperenderer.setBaseItemLabelsVisible(true); xylineandshaperenderer.setSeriesFillPaint(0, new Color(127, 128, 0)); xylineandshaperenderer.setSeriesPaint(0, new Color(127, 128, 0)); xylineandshaperenderer.setSeriesShapesVisible(0, true); xylineandshaperenderer.setSeriesShapesVisible(1, true); //第二条折线的颜色 xylineandshaperenderer.setSeriesFillPaint(1, new Color(254, 103, 0)); xylineandshaperenderer.setSeriesPaint(1, new Color(254, 103, 0)); xylineandshaperenderer.setSeriesShapesVisible(1, true); xylineandshaperenderer.setSeriesVisible(2, false);// xylineandshaperenderer.setSeriesVisible(3, false);//不显示下面标题 //折线的粗细调 StandardXYToolTipGenerator xytool = new StandardXYToolTipGenerator(); xylineandshaperenderer.setToolTipGenerator(xytool); xylineandshaperenderer.setStroke(new BasicStroke(1.5f)); // 显示节点的值 xylineandshaperenderer.setBaseItemLabelsVisible(true); xylineandshaperenderer .setBasePositiveItemLabelPosition(new ItemLabelPosition( ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_CENTER)); xylineandshaperenderer .setBaseItemLabelGenerator(new StandardXYItemLabelGenerator()); xylineandshaperenderer.setBaseItemLabelPaint(new Color(102, 102, 102));// 显示折点数值字体的颜色 http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 12 / 40 页 return jfreechart; } 4、将图片URL返回到页面 public static void drawPressLineChart(IrisIoInterface io, Log log, TimeSeriesCollection timesers, int weekormonth, String title, String y, String index, String week, String year, int searchby, String month, String nodatamess, List list, String bp_shou, String bp_shuzhang) { JFreeChart chart = createChartPress(timesers, weekormonth, title, y, index, week, year, searchby, month, nodatamess, list, log, bp_shou, bp_shuzhang); HttpServletRequest request = io.getRequest(); String filename = ""; String graphURL = ""; try { filename = ServletUtilities.saveChartAsPNG(chart, 650, 280, null, io.getSession()); graphURL = request.getContextPath() + "/displayChart?filename=" + filename; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); log.error(e); } io.setData("filename1", filename, BeanShare.BEAN_SHARE_REQUEST); io.setData("presslineurl", graphURL, BeanShare.BEAN_SHARE_REQUEST); } 效果图如下: http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 13 / 40 页 以天为刻度: 以周为刻度: 以月为刻度: http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 14 / 40 页 http://julianna-only.javaeye.com 1.1 JfreeChart折线图 第 15 / 40 页 1.2 JfreeChart 3D柱状图 带基准线的 发表时间: 2009-05-22 关键字: 3d 基准线 [/color]public static void drawInAndOutCalChart(String title,String bar1, String bar2, IrisIoInterface io, Connection con, List intakeAndSportCal, OnlineUser onlineUser, Log log, int drawBy) { int size = intakeAndSportCal.size(); double[][] data = new double[2][size]; String[] rowKeys = { bar1, bar2 }; String[] columnKeys = new String[size]; String noDataMessage = "you have not any recoreds!"; // 将摄入卡路里与运动卡路里放入到data数组中去。 double bmr = getUserBMRByBlogId(con, log, io, onlineUser); for (int i = 0; i < 2; i++) { for (int j = 0; j < size; j++) { UserFoodRecordBean re = (UserFoodRecordBean) intakeAndSportCal .get(j); if (i == 0) { data[i][j] = re.getCaloriesimple(); System.out.println("data[][] calsimple=" + data[i][j]); } else { if (drawBy == 1) { bmr = bmr * 1; } else if (drawBy == 2) { bmr = bmr * 1; } data[i][j] = re.getSportTotalCalorie() + bmr; } System.out.println("drawsportCal= ^^^^^^^^^^^^^^^^^=" + re.getSportTotalCalorie()); http://julianna-only.javaeye.com 1.2 JfreeChart 3D柱状图 带基准线的 第 16 / 40 页 } } for (int x = 0; x < size; x++) { UserFoodRecordBean re = (UserFoodRecordBean) intakeAndSportCal .get(x); columnKeys[x] = re.getUserfoodDate(); System.out.println("user_date=" + columnKeys[x]); } CategoryDataset dataset = DatasetUtilities.createCategoryDataset( rowKeys, columnKeys, data); JFreeChart chart = ChartFactory.createBarChart3D(title, null, null, dataset, PlotOrientation.VERTICAL, true, false, false); chart.setBackgroundPaint(Color.WHITE); CategoryPlot plot = chart.getCategoryPlot(); CategoryAxis domainAxis = plot.getDomainAxis(); // domainAxis.setVerticalCategoryLabels(false); plot.setDomainAxis(domainAxis); plot.setNoDataMessage(noDataMessage); String unit = "cal"; String label = "BMR=" + bmr + unit; ValueMarker valuemarker = new ValueMarker(bmr); valuemarker.setLabelOffsetType(LengthAdjustmentType.EXPAND); valuemarker.setPaint(Color.PINK); valuemarker.setStroke(new BasicStroke(1.0F)); valuemarker.setLabel(label); valuemarker.setLabelFont(new Font("SansSerif", 0, 11)); valuemarker.setLabelPaint(Color.blue); valuemarker.setLabelAnchor(RectangleAnchor.TOP_LEFT); valuemarker.setLabelTextAnchor(TextAnchor.BOTTOM_LEFT); http://julianna-only.javaeye.com 1.2 JfreeChart 3D柱状图 带基准线的 第 17 / 40 页 valuemarker.setLabelOffset(new RectangleInsets(5, 5, 5, 5)); float[] f = { 2, 4, 2, 4 }; valuemarker.setStroke(new BasicStroke(2.0f, 1, 1, 0, f, 1.0f)); // setStroke 将基准线 设置为虚线,float[]数组实现。 plot.addRangeMarker(valuemarker, Layer.BACKGROUND); ValueAxis rangeAxis = plot.getRangeAxis(); // 设置最高的一个 Item 与图片顶端的距离 rangeAxis.setUpperMargin(0.15); // 设置最低的一个 Item 与图片底端的距离 rangeAxis.setLowerMargin(0.15); plot.setRangeAxis(rangeAxis); BarRenderer3D renderer = new BarRenderer3D(); renderer.setBaseOutlinePaint(Color.BLACK); // 设置 Wall 的颜色 renderer.setWallPaint(Color.gray); // 设置每种卡路里代表的柱的颜色 renderer.setSeriesPaint(1, Color.red); renderer.setSeriesPaint(0, Color.GREEN); // 设置每种卡路里所包含的平行柱的之间距离 renderer.setItemMargin(0.05); // 显示每个柱的数值,并修改该数值的字体属性 renderer .setItemLabelGenerator(new StandardCategoryItemLabelGenerator()); renderer.setItemLabelsVisible(true); plot.setRenderer(renderer); // 设置柱的透明度 plot.setForegroundAlpha(0.6f); // 设置每种卡路里的显示位置 plot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_RIGHT); plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT); HttpServletRequest request = io.getRequest(); http://julianna-only.javaeye.com 1.2 JfreeChart 3D柱状图 带基准线的 第 18 / 40 页 String filename = ""; String graphURL = ""; try { filename = ServletUtilities.saveChartAsPNG(chart, 750, 172, null, io.getSession()); graphURL = request.getContextPath() + "/displayChart?filename=" + filename; System.out.println(filename); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } io.setData("filename", filename, BeanShare.BEAN_SHARE_REQUEST); io.setData("graphURL", graphURL, BeanShare.BEAN_SHARE_REQUEST); io.setData("bmr", bmr, BeanShare.BEAN_SHARE_REQUEST); }[/size] http://julianna-only.javaeye.com 1.2 JfreeChart 3D柱状图 带基准线的 第 19 / 40 页 1.3 JfreeChart 3D饼图总结 发表时间: 2009-12-08 今天抽空,也总结了一下3D饼图的画法,这里大致先写个思路。 1、取得数据集所需数据源。3D饼图的数据集通常用DefaultPieDataset,下面将我的代码粘一下: private static PieDataset createDataset(double[] datas, String foodfect, String bmr, String daily, String sport) { // String foodfect = "食物热效应"; // String bmr = "基础代谢率"; // String daily = "日常活动消耗的能量"; // String sport = "额外运动消耗"; double fectper = datas[3] / datas[1] * 100; double bmrper = datas[2] / datas[1] * 100; double dailper = datas[4] / datas[1] * 100; double sportper = datas[7] / datas[1] * 100; if (fectper >= 0 && bmrper >= 0 && dailper >= 0 && sportper >= 0) { fectper = Double.parseDouble(BarChartData .formAtCaloriepercent(fectper)); bmrper = Double.parseDouble(BarChartData .formAtCaloriepercent(bmrper)); dailper = Double.parseDouble(BarChartData .formAtCaloriepercent(dailper)); sportper = Double.parseDouble(BarChartData .formAtCaloriepercent(sportper)); } DefaultPieDataset pset = new DefaultPieDataset(); pset.setValue(foodfect, -fectper); pset.setValue(bmr, -bmrper); pset.setValue(daily, -dailper); http://julianna-only.javaeye.com 1.3 JfreeChart 3D饼图总结 第 20 / 40 页 pset.setValue(sport, -sportper); return pset; } 2、调用画图API /** * 饼状图 * @param dataset * 数据集 * @param chartTitle * 图标题 * @param charName * 生成图的名字 * @param pieKeys * 分饼的名字集 * @return */ public static JFreeChart createValidityComparePimChar(PieDataset dataset, String chartTitle, String nodatamess) { JFreeChart chart = ChartFactory.createPieChart3D("Pie Chart 3D Demo 3", dataset, true, true, false); PiePlot3D plot = (PiePlot3D) chart.getPlot(); plot.setStartAngle(290D); plot.setDirection(Rotation.CLOCKWISE); plot.setForegroundAlpha(0.5F); plot.setNoDataMessage("No data to display"); // 使下说明标签字体清晰,去锯齿类似于的效果 chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); // chart.setAntiAlias(false); // 图片背景色 http://julianna-only.javaeye.com 1.3 JfreeChart 3D饼图总结 第 21 / 40 页 chart.setBackgroundPaint(Color.WHITE); // 设置图标题的字体重新设置title // 设置标题的颜色 TextTitle text = new TextTitle(chartTitle); text.setPaint(new Color(102, 102, 102)); chart.setTitle(text); plot.setBackgroundPaint(new Color(255, 253, 246)); plot.setOutlineStroke(new BasicStroke(1.5f)); plot.setMaximumLabelWidth(0.25d); // 图片中显示百分比:默认方式 // 设置各色块的颜色 plot.setSectionPaint(0, new Color(87, 149, 117)); plot.setSectionPaint(1, new Color(234, 162, 40)); plot.setSectionPaint(2, new Color(197, 180, 127)); plot.setSectionPaint(3, new Color(75, 178, 197)); plot.setSectionPaint(4, new Color(131, 149, 87)); plot.setShadowXOffset(1.0d); plot.setIgnoreZeroValues(false); plot.setStartAngle(90); // 设置旋转角度 plot.setDirection(Rotation.CLOCKWISE); // 设置旋转方向 plot.setForegroundAlpha(0.5f); plot.setLabelLinkMargin(0.1); plot.setSectionOutlinesVisible(false); plot.setDepthFactor(0.1d);// 饼图的Z轴高度。 // 设置无数据时的信息 plot.setNoDataMessage(nodatamess); plot.setNoDataMessageFont(new Font("", Font.BOLD, 14)); http://julianna-only.javaeye.com 1.3 JfreeChart 3D饼图总结 第 22 / 40 页 // 设置无数据时的信息显示颜色 plot.setNoDataMessagePaint(new Color(87, 149, 117)); // 图片中显示百分比:自定义方式,{0} 表示选项, {1} 表示数值, {2} 表示所占比例 ,小数点后两位 plot.setLabelGenerator(new StandardPieSectionLabelGenerator( "{0} ={1}%", NumberFormat.getNumberInstance(), new DecimalFormat("0.00%"))); // 图例显示百分比:自定义方式, {0} 表示选项, {1} 表示数值, {2} 表示所占比例 plot.setLegendLabelGenerator(new StandardPieSectionLabelGenerator( "{0} ={1}%")); plot.setLabelFont(new Font("SansSerif", Font.TRUETYPE_FONT, 12)); // 指定图片的透明度(0.0-1.0) plot.setForegroundAlpha(0.65f); return chart; } 3、生成Chart图,返回图片URL public static void drawPieChart(IrisIoInterface io, Log log, double[] datas, String nodatamess, String foodfect, String bmr, String daily, String sport) { PieDataset dataset = createDataset(datas, foodfect, bmr, daily, sport); JFreeChart chart = createValidityComparePimChar(dataset, "", nodatamess); HttpServletRequest request = io.getRequest(); String filename = ""; String graphURL = ""; try { http://julianna-only.javaeye.com 1.3 JfreeChart 3D饼图总结 第 23 / 40 页 filename = ServletUtilities.saveChartAsPNG(chart, 320, 177, null, io.getSession()); graphURL = request.getContextPath() + "/displayChart?filename=" + filename; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); log.error(e); } io.setData("filename1", filename, BeanShare.BEAN_SHARE_REQUEST); io.setData("pieurl", graphURL, BeanShare.BEAN_SHARE_REQUEST); } 现在就OK了,效果图: http://julianna-only.javaeye.com 1.3 JfreeChart 3D饼图总结 第 24 / 40 页 1.4 JfreeChart 散点图,加了区域范围说明 发表时间: 2009-12-08 用JfreeChart画散点图,查看JfreeChart的Demo,写的都挺复杂的,关键是Demo中把简单的事情复杂化了, 比如展示的例子是一个正弦曲线什么的,让初次画散点图的我们摸不着头脑。关键是他们得到数据集搞得太过 复杂,后来想明白了,不就是二维数组嘛。想通了这一点,一切问题都解决了,不过,对于我们项目的特殊要 求,并不是只画几个点那么简单,还要加上区域范围与文字说明,在查看文档及自己摸索下,2天时间,终于搞 定。下面分享一下成果,呵,还是有点成就感的。 首先,看画图的API,参数有: ChartFactory.createScatterPlot(),其中,有一个xydataset,那么,我们先要知道这个xydataset是什么结 构的,再看所需xydataset,散点图,也就是单独画出点,也就是一个二维数据了,x ,y坐标嘛! 那么,先做好准备工作,第一步,拿数据,这就不用啰嗦了,就是得到一个List也好,Set也行。 第二步,加载到数据集: /** * * @param xydatalist * @param bloods * @return */ public static XYDataset createxydataset(List xydatalist, String bloods) { DefaultXYDataset xydataset = new DefaultXYDataset(); int size = xydatalist.size(); double[][] datas = new double[2][size]; for (int i = 0; i < size; i++) { PressureBean pres = xydatalist.get(i); int sys = pres.getSyspress();//收缩压 int dia = pres.getDiapress();//舒张压 datas[0][i] = sys; datas[1][i] = dia; } http://julianna-only.javaeye.com 1.4 JfreeChart 散点图,加了区域范围说明 第 25 / 40 页 xydataset.addSeries(bloods, datas); return xydataset; } 下一步,另外一个准备工作,画图方法: public static JFreeChart createChart(XYDataset xydataset, String bloodcattile, String shou, String shu, String nobloodData, String bloods, String nomal, String fore, String one, String two, List list, Log log) { // 有可能用户在后面的版本中故意输入不正常数值,但是为了保证图片画图的完整,这里先计算 // 用户血压值的最大值。 int maxpress = 160; int addmax = 20; if (list != null && list.size() > 0) { Iterator it = list.iterator(); while (it.hasNext()) { PressureBean pres = it.next(); if (maxpress < pres.getDiapress()) { maxpress = pres.getDiapress(); } if (maxpress < pres.getSyspress()) { maxpress = pres.getSyspress(); } } maxpress += addmax; http://julianna-only.javaeye.com 1.4 JfreeChart 散点图,加了区域范围说明 第 26 / 40 页 log.info("high press value is =" + maxpress); } JFreeChart jfreechart = ChartFactory.createScatterPlot(bloodcattile, shou, shu, xydataset, PlotOrientation.VERTICAL, true, false, false); jfreechart.setBackgroundPaint(Color.white); jfreechart.setBorderPaint(Color.GREEN); jfreechart.setBorderStroke(new BasicStroke(1.5f)); XYPlot xyplot = (XYPlot) jfreechart.getPlot(); xyplot.setNoDataMessage(nobloodData); xyplot.setNoDataMessageFont(new Font("", Font.BOLD, 14)); xyplot.setNoDataMessagePaint(new Color(87, 149, 117)); xyplot.setBackgroundPaint(new Color(255, 253, 246)); ValueAxis vaaxis = xyplot.getDomainAxis(); vaaxis.setAxisLineStroke(new BasicStroke(1.5f)); ValueAxis va = xyplot.getDomainAxis(0); va.setAxisLineStroke(new BasicStroke(1.5f)); va.setAxisLineStroke(new BasicStroke(1.5f)); // 坐标轴粗细 va.setAxisLinePaint(new Color(215, 215, 215)); // 坐标轴颜色 xyplot.setOutlineStroke(new BasicStroke(1.5f)); // 边框粗细 va.setLabelPaint(new Color(10, 10, 10)); // 坐标轴标题颜色 va.setTickLabelPaint(new Color(102, 102, 102)); // 坐标轴标尺值颜色 ValueAxis axis = xyplot.getRangeAxis(); axis.setAxisLineStroke(new BasicStroke(1.5f)); XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyplot .getRenderer(); xylineandshaperenderer.setSeriesOutlinePaint(0, Color.WHITE); xylineandshaperenderer.setUseOutlinePaint(true); NumberAxis numberaxis = (NumberAxis) xyplot.getDomainAxis(); http://julianna-only.javaeye.com 1.4 JfreeChart 散点图,加了区域范围说明 第 27 / 40 页 numberaxis.setAutoRangeIncludesZero(false); numberaxis.setTickMarkInsideLength(2.0F); numberaxis.setTickMarkOutsideLength(0.0F); numberaxis.setAxisLineStroke(new BasicStroke(1.5f)); numberaxis.setUpperBound(maxpress); numberaxis.setLowerBound(60);//最小值设置为60 NumberAxis numberaxis1 = (NumberAxis) xyplot.getRangeAxis(); numberaxis1.setTickMarkInsideLength(2.0F); numberaxis1.setTickMarkOutsideLength(0.0F); numberaxis1.setUpperBound(105d); numberaxis1.setLowerBound(35); numberaxis1.setAxisLineStroke(new BasicStroke(1.5f)); // if (xydataset != null) { XYBoxAnnotation box = new XYBoxAnnotation(0, 0, 89, 59); //正常血压所在区域内边界 XYBoxAnnotation box1 = new XYBoxAnnotation(0, 0, 119, 79);//高血压前期所在区域内边界 XYBoxAnnotation box2 = new XYBoxAnnotation(0, 0, 139, 89);//高血压一期所在区域内边界 XYBoxAnnotation box3 = new XYBoxAnnotation(0, 0, 159, 99);//高血压二期所在区域内边界 XYTextAnnotation text1 = new XYTextAnnotation(nomal, 70, 62.5);//标识“正常” XYTextAnnotation text = new XYTextAnnotation(fore, 70, 82.5);//“高血压前期” XYTextAnnotation text2 = new XYTextAnnotation(one, 70, 91.5);//“高血压一期” XYTextAnnotation text3 = new XYTextAnnotation(two, 70, 101.5);//“高血压二期” //将上面的边界线条,说明文字加入到xyplot中。 xyplot.addAnnotation(box); xyplot.addAnnotation(box1); xyplot.addAnnotation(box2); xyplot.addAnnotation(box3); xyplot.addAnnotation(text); xyplot.addAnnotation(text1); xyplot.addAnnotation(text2); xyplot.addAnnotation(text3); // } return jfreechart; } http://julianna-only.javaeye.com 1.4 JfreeChart 散点图,加了区域范围说明 第 28 / 40 页 最后一步,返回图片URL public static void drawScatterChart(IrisIoInterface io, Log log, XYDataset xydataSet, String title, String shou, String shu, String nodata, String boolds, String nomal, String fore, String one, String two, List list) { JFreeChart chart = createChart(xydataSet, title, shou, shu, nodata, boolds, nomal, fore, one, two, list, log); HttpServletRequest request = io.getRequest(); String filename = ""; String graphURL = ""; try { filename = ServletUtilities.saveChartAsPNG(chart, 400, 300, null, io.getSession()); graphURL = request.getContextPath() + "/displayChart?filename=" + filename; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); log.error(e); } io.setData("filename", filename, BeanShare.BEAN_SHARE_REQUEST); io.setData("scatterurl", graphURL, BeanShare.BEAN_SHARE_REQUEST); } 效果图: http://julianna-only.javaeye.com 1.4 JfreeChart 散点图,加了区域范围说明 第 29 / 40 页 http://julianna-only.javaeye.com 1.4 JfreeChart 散点图,加了区域范围说明 第 30 / 40 页 1.5 JfreeChart热点map的应用 发表时间: 2010-01-15 今天主要总结一下JfreeChart中热点map的应用,根据我个人的理解来总结的,可能会有某些地方不是很 正确,如有错误,请大家指正,不断改进。 首先,这里的热点的应用在于用户与JfreeChart图像的交互,也就是与图像文件(因为我们是将Chart对象 以二进制数据写入一个图像文件了,比如PNG文件,JPEG图像文件)交互。在HTML中,为了让一个图像具有 可交互的功能就必须给该图像定义一个Map对象,然后在 也就是在img标签的usemap属性上,指定map对象。 下面举例说明,用JfreeChart在这个图像中产生热点。 那么它的原始map数据大致为: http://julianna-only.javaeye.com 1.5 JfreeChart热点map的应用 第 31 / 40 页 这里面,shape是指热点的区域,本段中的poly是一个多边形,也有Rectangle等。Coords是这个多边形的坐标, 通常是需要用工具生成,这里所展示的是JfreeChart自动生成的。Title=””中的内容便是mouse移到各个点时, 展示出的信息,mouse移开后信息不再显示。这里不需要我们再写别的代码,个人理解是,浏览器可以解析这部分数据, 相当于将title的内容在onmouseover中显示。 那么,现在的问题就在于,怎么获得map数据了。 当然是根据一个图像来生成对应的MAP对象。 在创建一个图表对象时候有两个参数,比如这里面的折线图的部分代码: JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(title, "", y, xydataset, true, true, false); 两个参数就是这个方法中的最后两个参数,这两个参数的类型都是布尔值。这两个参数意思分别是:是否创建工具提 示(tooltip)以及是否生成URL。这两个参数分别对应着MAP中一个AREA的title属性以及href属性。 可是我想知道的是怎么来产生这个MAP啊!哈哈,不要着急,JFreeChart已经帮我们做好生成MAP对象的功能。为了生 成MAP对象就要引入另外一个对象:ChartRenderingInfo。因为JFreeChart没有直接的方法利用一个图表对象直接生 成MAP数据,它需要一个中间对象来过渡,这个对象就是ChartRenderingInfo。下图是生成MAP数据的流程图: 如上图所示,ChartUtilities类是整个流程的核心,它周围的对象都是一些例如数据对象或者是文件等。这个流 程简单描述如下:首先创建一个ChartRenderingInfo对象并在调用ChartUtilities的writeChartAsJPEG时作为 最后一个参数传递进去。调用该方法结束后将产生一个图像文件以及一个填充好MAP数据 的ChartRenderingInfo对象,有了这个对象我们还是没有办法获取具体的MAP数据,我们还必须借助 于ChartUtilities的writeImageMap方法来将ChartRenderingInfo对象读取出来,获取MAP数据的代码片断如 下: JFreeChart chart = createCaloriesLineChart(timesers, weekormonth, title, avgenergy + "(" + y + ")", index, week, year1,year, nodatamess, maxcalorie, month); HttpServletRequest request = io.getRequest(); http://julianna-only.javaeye.com 1.5 JfreeChart热点map的应用 第 32 / 40 页 String filename = ""; String graphURL = ""; PrintWriter writer = null; try { io.getResponse().setContentType("text/html"); io.getResponse().setCharacterEncoding("UTF-8"); // 这里要设置一下,因为这里相当于用PrintWriter将图片写出来,如果不设置字符集,则默认为ISO-8859-1,而页面用的是UTF-8. writer = io.getResponse().getWriter(); Shape shape = new Rectangle(10, 5); ChartEntity entity = new ChartEntity(shape); StandardEntityCollection coll = new StandardEntityCollection(); coll.add(entity); ChartRenderingInfo info = new ChartRenderingInfo(coll); filename = ServletUtilities.saveChartAsPNG(chart, 720, 250, info, io.getSession()); ChartUtilities.writeImageMap(writer, filename, info, true); graphURL = request.getContextPath() + "/displayChart?filename=" + filename; String strimg = ChartUtilities.getImageMap(filename, info); 当初在实现这个拿到map数据时,花费了不少时间,根据writeImageMap()回溯到找寻如何得到 info,要 得到info又如何得到StandardEntityCollection对象,以 及StandardEntityCollection与ChartEntity、Shape的关联,这个就需要花时间好好研究API了,感 觉JfreeChart API写的太过于简单,需要自己动手试试一些方法才可以完成,不过感觉这部分还是比较单一的 需求,感觉在图象对象其他的类上,过于复杂,文档过于简单,我们必须去了解每个类型的图表对象应该对应 哪些Axis、Plot、Renderer类,并且必须非常熟悉这些类的构造函数中每个参数的具体含义才可以少走弯路, 对于某些特定的需求,比如柱状图与折线图并存时,可不可以用XYPlot,只有试过,根据报错的信息才知道这 样做是不可以的。好了,别的感慨不多说了。这里的strimg的内容就是map对象。 自己实现响应mouse事件 http://julianna-only.javaeye.com 1.5 JfreeChart热点map的应用 第 33 / 40 页 上图的map热点信息,大家可以看出,过于简单、表达的方式的不常规很难满足产品的需求,至少要以 比较直观的、清晰的方式来表达信息,并且,如果单单只写出X、Y坐标对应的值,相信map热点的存在就是多 余,just a Demo.所以为了满足产品级别需求,我们需要自己实现响应mouse事件。 这个解决方案有多种,我是根据自己的理解,将很规则的map数据解析,根据X轴时间取到关联这一天、周、 月的详细信息,然后将解析、重组后的数据以变量传到onmouseover事件中。 当然,怎么样让数据与map中各标签的内容一致,以及后续的Tip定位问题,也是需要考虑的。为了方 便,这里需要给每个area节点再加一个属性id,并赋值。 StringReader reader = new StringReader(strimg); InputSource source = new InputSource(reader); SAXBuilder build = new SAXBuilder(); try { Document doc = build.build(source); Element element = doc.getRootElement(); List list = element.getChildren(); int size1 = list.size(); for (int j = 0; j < size1; j++) { String nstr = ""; Element e = list.get(j); Attribute att = e.getAttribute("title"); String value = att.getValue(); value = value.replace("(", ""); value = value.replace(")", ""); Attribute bute = new Attribute("id", j + ""); e.setAttribute(bute); int id = bute.getIntValue(); int ind = j; if (j >= size1 / 2) { ind = j - (size1 / 2); http://julianna-only.javaeye.com 1.5 JfreeChart热点map的应用 第 34 / 40 页 } UserFoodRecordBean r = (UserFoodRecordBean) calories .get(ind); double bike = r.getBikeCalorie(); double bmrto = r.getBmrTotal(); double sport = r.getSpcal(); double foodcal = r.getCaloriesimple(); double fect=r.getFoodfec(); double cyclomer=r.getCycal(); double total1 = r.getSportTotalCalorie(); double balance = foodcal - total1; double dailywork = r.getDailyworkcalorie(); String datestr = r.getUserfoodDate(); if (weekormonth == 0) { datestr = BarChartData.formAtDate(datestr); } else { String[] das = datestr.split("-"); int weekindex = Integer.parseInt(das[1]); if (weekormonth == 1) { datestr = das[0] + year + index1 + weekindex + week; } else { datestr = das[0] + year1 + weekindex + month; } } balance = Double.parseDouble(BarChartData .formAtCalorie(balance)); nstr += "date=" + datestr + "&BMR=" + bmrto + "&"; if (bike > 0) { http://julianna-only.javaeye.com 1.5 JfreeChart热点map的应用 第 35 / 40 页 nstr += "e-Bike=" + bike + "&"; } if (sport > 0) { nstr += "sport=" + sport + "&"; } if(cyclomer>0){ nstr+="cyclemer="+cyclomer+"&"; } if(fect>0){ nstr+="fect="+fect+"&"; } nstr += "food=" + foodcal + "&" + "total=" + total1 + "&balance=" + balance + "&dailywork=" + dailywork; // nstr=HtmlUtils.htmlUnescape(nstr); att.setValue("");// set nstr to title String over = "showChartTips('" + nstr + "','" + id + "',event);"; String out = "chartlivess();"; Attribute bu = new Attribute("onmouseover", over); e.setAttribute(bu); Attribute outatt = new Attribute("onmouseout", out); e.setAttribute(outatt); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter pw = new PrintWriter(baos); // 用PrintWriter可以解决生成编码为UTF-8格式的XML内容出现中文乱码的问题 http://julianna-only.javaeye.com 1.5 JfreeChart热点map的应用 第 36 / 40 页 Format format = Format.getPrettyFormat(); format.setEncoding("UTF-8"); XMLOutputter output = new XMLOutputter(); output.setFormat(format); output.output(doc, pw); String strs = baos.toString(); int j = strs.indexOf("= 0){ top=window.scrollY + e.clientY; left=window.scrollX+e.clientX; _tips.style.left=left+"px"; _tips.style.top = top+"px"; } } PS: 部分内容转自http://www.ibm.com/developerworks/cn/java/l-jfreechart/ 作者 刘冬 如果大家之前没有接触过JfreeChart或者是初学者,可以先看看这篇文章 。当初我在实现这个热点map时,感 觉这篇文章写的很详细,对我也很有帮助,不过,我实现的具体方案还是经过多次尝试、多次调整,毕竟我这 里的要求更高,呵呵 http://julianna-only.javaeye.com 1.5 JfreeChart热点map的应用 第 39 / 40 页 1.6 JfreeChart如何处理乱码 发表时间: 2010-08-12 今天在JE问答上答题,一个关于JfreeChart如何处理乱码问题。我之前一直是将中文,繁体或者简体转成 unicode码的。后来发现将jfreeChart的ChartTheme设置成unicode也是可以的。记录一下。 StandardChartTheme theme = new StandardChartTheme("unicode") { public void apply(JFreeChart chart) { chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); super.apply(chart); } }; theme.setExtraLargeFont(new Font("宋体", Font.PLAIN, 20)); theme.setLargeFont(new Font("宋体", Font.PLAIN, 14)); theme.setRegularFont(new Font("宋体", Font.PLAIN, 12)); theme.setSmallFont(new Font("宋体", Font.PLAIN, 10)); ChartFactory.setChartTheme(theme); http://julianna-only.javaeye.com 1.6 JfreeChart如何处理乱码 第 40 / 40 页
还剩39页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 15 金币 [ 分享pdf获得金币 ] 9 人已下载

下载pdf

pdf贡献者

sweetbaybe

贡献于2011-07-09

下载需要 15 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf