如何在JFreeChart柱状图中实现X轴(域轴)缩放?
当然可以实现X轴缩放!
默认情况下,CategoryPlot(普通柱状图用的绘图区)的域轴是分类轴(CategoryAxis),它是离散的,所以JFreeChart自带的缩放功能对它不生效——这也是为什么时间序列图(用XYPlot,轴是连续的数值轴)能直接支持缩放的原因。针对你有数百个柱子的场景,最简便的解决方案是把分类数据转换为XY数据集,使用XYBarChart来创建图表,这样就能利用数值轴的原生缩放功能了。
修改后的代码示例
下面是调整后的代码,把原来的分类数据集转换成XY数据集,生成支持X轴缩放的柱状图:
Random rand = new Random(); // 创建XY系列,把分类序号作为X值,对应数值作为Y值 XYSeries series = new XYSeries("test"); for(int i=1;i<201;i++){ series.add(i, rand.nextInt(50) + 1); } XYSeriesCollection dataset = new XYSeriesCollection(series); // 创建XY柱状图,代替原来的普通柱状图 JFreeChart chart = ChartFactory.createXYBarChart( title, // 图表标题 "pages", // 域轴标签 false, // 是否为日期轴(这里我们用数值轴,所以设为false) "Value", // 范围轴标签 dataset, PlotOrientation.VERTICAL, true, // 显示图例 true, // 显示工具提示 false // 不生成URL ); ChartPanel chart_panel = new ChartPanel(chart); // 开启鼠标缩放和滚轮缩放 chart_panel.setMouseZoomable(true); chart_panel.setMouseWheelEnabled(true); XYPlot plot = (XYPlot) chart.getPlot(); plot.setBackgroundPaint(Color.WHITE); XYBarRenderer renderer = (XYBarRenderer) plot.getRenderer(); renderer.setBarPainter(new StandardBarPainter()); renderer.setDrawBarOutline(false); // 调整柱子间距,避免过于拥挤 renderer.setMargin(0.2); this.add(chart_panel);
额外优化:自定义分类标签
如果你的分类不是数字(比如是字符串标签),可以给数值轴设置自定义的刻度格式化器,把X轴的数值映射回原来的分类文本:
NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis(); // 设置刻度间隔为1,对应每个分类 domainAxis.setTickUnit(new NumberTickUnit(1)); // 自定义刻度标签格式 domainAxis.setTickLabelFormatter(new NumberFormat() { @Override public String format(double number) { // 这里可以根据数值返回对应的分类文本,比如用Map映射 // 示例:如果原来的分类是"分类1"、"分类2"...就返回对应字符串 return "分类" + (int) number; } @Override public String format(long number) { return format((double) number); } // 其他未用到的方法可以直接抛出异常,或者空实现 @Override public Number parse(String source, ParsePosition parsePosition) { throw new UnsupportedOperationException(); } });
效果说明
修改后,你可以:
- 按住鼠标左键拖动,框选想要放大的X轴区域;
- 滚动鼠标滚轮,实现平滑的缩放;
- 右键点击图表,选择"Restore AutoBounds"恢复默认视图。
这种方式完全利用JFreeChart原生的缩放机制,不需要复杂的自定义逻辑,非常适合处理大量柱子的场景。
内容的提问来源于stack exchange,提问作者Alex Torrisi
相关产品推荐
相关产品推荐

