You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:16:01