JFreeChart折线图如何实现垂直刻度处交替切换背景色
JFreeChart折线图实现垂直刻度位置交替背景色方案
setRangeTickBandPaint是XYPlot类的专属API,如果你创建折线图时用的是分类数据集、生成的Plot为CategoryPlot类型,就找不到这个方法,分两种场景实现即可:
场景1:折线图使用数值X轴(XYDataset)
如果你是用ChartFactory.createXYLineChart创建的折线图(比如时序图、连续数值X轴的折线图),不需要额外开发,直接强转Plot类型调用内置API即可:
// 创建折线图后获取Plot对象 JFreeChart lineChart = ChartFactory.createXYLineChart( "图表标题", "X轴标签", "Y轴标签", dataset, PlotOrientation.VERTICAL, true, true, false ); XYPlot plot = (XYPlot) lineChart.getPlot(); // 配置交替带颜色(浅灰色,和参考效果匹配) plot.setRangeTickBandPaint(new Color(237, 237, 237)); // 配置间隔的另一种背景色为纯白色 plot.setBackgroundPaint(Color.WHITE);
直接运行就能得到Y轴刻度位置交替切换的横向背景带效果。
场景2:折线图使用分类X轴(CategoryDataset)
如果你是用ChartFactory.createLineChart创建的分类折线图(X轴是文本分类标签,不是连续数值),CategoryPlot没有内置自动绘制交替带的逻辑,推荐两种实现方式,优先选第一种性能更好:
方式1:重写Plot的背景绘制方法(推荐)
自定义CategoryPlot子类,重写背景绘制逻辑,在原有背景绘制完成后,按Y轴刻度间隔交替填充色,不会影响上层数据、网格线的绘制:
CategoryPlot plot = new CategoryPlot() { @Override protected void drawBackground(Graphics2D g2, Rectangle2D plotArea, PlotRenderingInfo info) { // 先绘制原有基础背景 super.drawBackground(g2, plotArea, info); NumberAxis yAxis = (NumberAxis) getRangeAxis(); double tickInterval = yAxis.getTickUnit().getSize(); double yMin = yAxis.getRange().getLowerBound(); double yMax = yAxis.getRange().getUpperBound(); RectangleEdge axisEdge = getRangeAxisEdge(); // 交替填充浅灰色带 g2.setPaint(new Color(237, 237, 237)); boolean needFill = false; for (double yVal = yMin; yVal < yMax; yVal += tickInterval) { if (needFill) { double y1 = yAxis.valueToJava2D(yVal, plotArea, axisEdge); double y2 = yAxis.valueToJava2D(yVal + tickInterval, plotArea, axisEdge); g2.fill(new Rectangle2D.Double( plotArea.getX(), Math.min(y1, y2), plotArea.getWidth(), Math.abs(y2 - y1) )); } needFill = !needFill; } } }; // 把原图表的数据集、X/Y轴、渲染器设置到自定义Plot实例上即可 plot.setDataset(dataset); plot.setDomainAxis(new CategoryAxis("X轴标签")); plot.setRangeAxis(new NumberAxis("Y轴标签")); plot.setRenderer(new LineAndShapeRenderer()); plot.setBackgroundPaint(Color.WHITE);
方式2:添加区间标记实现(代码简单,适合数据量小的场景)
不需要自定义子类,遍历Y轴刻度,给Plot添加背景层的区间标记即可实现效果,缺点是刻度多的时候渲染性能稍差:
CategoryPlot plot = (CategoryPlot) lineChart.getPlot(); plot.setBackgroundPaint(Color.WHITE); NumberAxis yAxis = (NumberAxis) plot.getRangeAxis(); double tickInterval = yAxis.getTickUnit().getSize(); double yMin = yAxis.getRange().getLowerBound(); boolean needFill = false; for (double yVal = yMin; yVal < yAxis.getRange().getUpperBound(); yVal += tickInterval) { if (needFill) { IntervalMarker band = new IntervalMarker(yVal, yVal + tickInterval, new Color(237, 237, 237)); band.setOutlinePaint(null); // 去掉带的边框 plot.addRangeMarker(band, Layer.BACKGROUND); // 放在背景层绘制 } needFill = !needFill; }
注意事项
- 交替带颜色建议用低饱和度浅灰,不要用透明度过高的颜色,避免遮挡网格线和折线数据
- 如果需要动态调整Y轴范围,记得在轴范围变更事件里清空旧的标记/刷新绘制,避免带的位置和刻度不匹配
内容的提问来源于stack exchange,提问作者TomC
相关产品推荐
相关产品推荐

