如何通过ChartMouseListener修改JFreeChart中选中点的大小、颜色并显示标签?
在JFreeChart中修改选中数据点的样式并显示标签
我来给你捋捋怎么实现这个需求哈!你已经通过ChartMouseListener拿到了选中点的索引,接下来核心是自定义渲染器——因为JFreeChart里是由渲染器负责绘制所有数据点的样式,我们需要让它对选中的点特殊处理。具体步骤如下:
1. 自定义XY渲染器
首先写一个继承自XYLineAndShapeRenderer(这是最常用的折线+点的渲染器,如果你用的是其他渲染器比如XYDotRenderer,换对应的父类就行)的自定义渲染器,在里面判断当前绘制的点是不是选中的那个,然后给它设置特殊样式:
class CustomXYRenderer extends XYLineAndShapeRenderer { // 记录选中的点的系列索引和项索引 private int selectedSeries = -1; private int selectedItem = -1; // 提供方法来设置选中的点,同时触发图表更新 public void setSelectedPoint(int series, int item) { this.selectedSeries = series; this.selectedItem = item; fireChangeEvent(); // 通知图表渲染状态改变 } @Override protected void drawItem(Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { // 判断当前绘制的点是不是选中的点 boolean isSelected = (series == selectedSeries && item == selectedItem); // 先保存当前点的默认样式,方便后续恢复 Shape defaultShape = getItemShape(series, item); Paint defaultPaint = getItemPaint(series, item); float defaultStrokeWidth = ((BasicStroke) getItemStroke(series, item)).getLineWidth(); if (isSelected) { // 给选中点设置特殊样式:放大2倍、红色填充、加粗边框 setItemShape(series, item, defaultShape.createTransformedShape(AffineTransform.getScaleInstance(2, 2))); setItemPaint(series, item, Color.RED); setItemStroke(series, item, new BasicStroke(2f)); // 开启选中点的标签显示,用默认的标签生成器(显示x、y值) setItemLabelVisible(series, item, true); setItemLabelGenerator(series, item, new StandardXYItemLabelGenerator()); } else { // 非选中点恢复默认样式 setItemShape(series, item, defaultShape); setItemPaint(series, item, defaultPaint); setItemStroke(series, item, new BasicStroke(defaultStrokeWidth)); // 非选中点隐藏标签(你也可以根据需求调整) setItemLabelVisible(series, item, false); } // 调用父类方法完成绘制 super.drawItem(g2, state, dataArea, info, plot, domainAxis, rangeAxis, dataset, series, item, crosshairState, pass); } }
2. 给图表设置自定义渲染器
在你初始化图表的代码里,把默认的渲染器替换成我们自定义的:
// 获取图表的XYPlot XYPlot plot = chart.getXYPlot(); // 创建自定义渲染器实例 CustomXYRenderer customRenderer = new CustomXYRenderer(); // 设置给plot plot.setRenderer(customRenderer);
3. 在鼠标点击事件中触发样式更新
回到你已经写好的ChartMouseListener,在点击事件里调用自定义渲染器的setSelectedPoint方法,然后重绘图表:
chartPanel.addChartMouseListener(new ChartMouseListener() { @Override public void chartMouseMoved(ChartMouseEvent arg0) { // 不需要处理移动事件可以留空 } @Override public void chartMouseClicked(ChartMouseEvent arg0) { JFreeChart chart = arg0.getChart(); if (chart == null) return; XYItemEntity ce = (XYItemEntity) arg0.getEntity(); if (ce == null) return; int sindex = ce.getSeriesIndex(); int iindex = ce.getItem(); // 获取我们的自定义渲染器 XYPlot plot = chart.getXYPlot(); CustomXYRenderer renderer = (CustomXYRenderer) plot.getRenderer(); // 设置选中的点 renderer.setSelectedPoint(sindex, iindex); // 重绘图表让样式生效 chartPanel.repaint(); } });
额外小贴士
- 如果需要支持取消选中(比如点击空白区域时恢复所有点的默认样式),可以在点击事件里判断如果点击的不是
XYItemEntity,就调用renderer.setSelectedPoint(-1, -1)。 - 标签内容可以自定义,比如实现
XYItemLabelGenerator接口来生成你想要的格式,比如只显示y值或者添加额外描述。 - 如果你的图表用的是其他类型的数据集(比如
CategoryDataset),思路是一样的,只需要换成对应的CategoryItemRenderer就行。
内容的提问来源于stack exchange,提问作者x zx
相关产品推荐
相关产品推荐

