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

Orson Charts中JFree Chart3D的XYZ折线图交互与数据获取问题

Orson Charts 3D折线图:选中高亮、数据集获取及折线段子数据集提取

先解决getRenderer() is undefined for type Plot3D错误

Orson Charts中Plot3D是顶层接口,3D折线图对应的实际实现类是XYZPlot,你需要先将Plot3D强转为XYZPlot,才能调用渲染器和数据集相关方法:

Chart3D chart = ...; // 你的3D图表实例
XYZPlot plot = (XYZPlot) chart.getPlot();
XYZRenderer3D renderer = plot.getRenderer();
XYZDataset dataset = plot.getDataset();

1. 高亮选中的折线

通过监听鼠标点击事件,获取选中的折线系列,修改其渲染样式(线条宽度、颜色)后触发图表重绘:

ChartPanel3D panel = new ChartPanel3D(chart);
panel.addMouseListener(new MouseAdapter() {
    private int lastSelectedSeries = -1;

    @Override
    public void mouseClicked(MouseEvent e) {
        PickResult pickResult = panel.getPickResult();
        if (pickResult != null && pickResult.getPickable() instanceof SeriesItem) {
            SeriesItem item = (SeriesItem) pickResult.getPickable();
            int selectedSeries = item.getSeriesIndex();
            XYZRenderer3D renderer = ((XYZPlot) chart.getPlot()).getRenderer();
            
            // 恢复上一次选中系列的默认样式
            if (lastSelectedSeries != -1) {
                renderer.setLineColor(lastSelectedSeries, Color.BLUE); // 替换为你的默认颜色
                renderer.setLineWidth(lastSelectedSeries, 1.0); // 替换为你的默认宽度
            }
            
            // 设置当前选中系列的高亮样式
            renderer.setLineColor(selectedSeries, Color.RED);
            renderer.setLineWidth(selectedSeries, 3.0);
            lastSelectedSeries = selectedSeries;
            
            // 触发图表重绘更新样式
            chart.fireChangeEvent();
        }
    }
});

2. 获取选中折线对应的数据集

拿到选中的系列索引后,直接从XYZDataset中提取该系列的所有数据:

// 承接上面的鼠标点击事件代码
XYZDataset dataset = ((XYZPlot) chart.getPlot()).getDataset();
Comparable<?> seriesKey = dataset.getSeriesKey(selectedSeries);
int itemCount = dataset.getItemCount(selectedSeries);

// 遍历该系列的所有数据点
for (int i = 0; i < itemCount; i++) {
    double x = dataset.getXValue(selectedSeries, i);
    double y = dataset.getYValue(selectedSeries, i);
    double z = dataset.getZValue(selectedSeries, i);
    // 按需处理数据,比如打印、存储
    System.out.printf("系列[%s] 点%d: (%.2f, %.2f, %.2f)%n", seriesKey, i, x, y, z);
}

3. 获取两次点击选中的折线段对应的子数据集

记录两次点击的点,验证属于同一系列后,提取两点之间的所有数据点组成子数据集:

ChartPanel3D panel = new ChartPanel3D(chart);
panel.addMouseListener(new MouseAdapter() {
    private SeriesItem firstClickItem = null;

    @Override
    public void mouseClicked(MouseEvent e) {
        PickResult pickResult = panel.getPickResult();
        if (pickResult != null && pickResult.getPickable() instanceof SeriesItem) {
            SeriesItem currentItem = (SeriesItem) pickResult.getPickable();
            if (firstClickItem == null) {
                firstClickItem = currentItem;
                JOptionPane.showMessageDialog(null, "已选中第一个点,请点击同一条折线的第二个点");
            } else {
                // 校验是否为同一系列
                if (firstClickItem.getSeriesIndex() != currentItem.getSeriesIndex()) {
                    JOptionPane.showMessageDialog(null, "请选择同一条折线上的点");
                    firstClickItem = null;
                    return;
                }
                
                int seriesIndex = firstClickItem.getSeriesIndex();
                int startIdx = Math.min(firstClickItem.getItemIndex(), currentItem.getItemIndex());
                int endIdx = Math.max(firstClickItem.getItemIndex(), currentItem.getItemIndex());
                
                XYZDataset sourceDataset = ((XYZPlot) chart.getPlot()).getDataset();
                DefaultXYZDataset subDataset = new DefaultXYZDataset();
                String segmentName = sourceDataset.getSeriesKey(seriesIndex).toString() + " 折线段";
                
                // 提取子数据点
                double[] xData = new double[endIdx - startIdx + 1];
                double[] yData = new double[endIdx - startIdx + 1];
                double[] zData = new double[endIdx - startIdx + 1];
                
                for (int i = startIdx; i <= endIdx; i++) {
                    int pos = i - startIdx;
                    xData[pos] = sourceDataset.getXValue(seriesIndex, i);
                    yData[pos] = sourceDataset.getYValue(seriesIndex, i);
                    zData[pos] = sourceDataset.getZValue(seriesIndex, i);
                }
                
                subDataset.addSeries(segmentName, new double[][]{xData, yData, zData});
                // 子数据集可用于生成新图表或其他业务处理
                JOptionPane.showMessageDialog(null, "已提取折线段子数据集,共包含" + (endIdx - startIdx + 1) + "个点");
                
                firstClickItem = null; // 重置选择状态
            }
        }
    }
});

内容的提问来源于stack exchange,提问作者Cengiz Eken

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:08:29