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
相关产品推荐
相关产品推荐

