JavaFX SmoothedChart绘制圆形时数据点连接异常
问题根源
你遇到的连线错乱问题核心原因有两个:
- JavaFX的
LineChart以及你用的SmoothedChart默认开启按X轴坐标值排序连线的策略,不管你按什么顺序添加数据点,渲染时都会把点按X值从小到大排列后依次连接。绘制圆形时,X值在180°位置到达最小值,角度从180°转到360°时X值会反向增大,连线就会直接横穿圆心,出现你截图里的错误效果。 - 你没有保证数据点按极角从0°到360°单调递增的顺序排列,也没有补充闭合点,就算关了排序也可能出现连线跳变、首尾不闭合的问题。
另外你代码里添加的空series2对绘图没有作用,可以直接删除。
修复方案
按下面的步骤调整代码即可:
- 强制设置图表的排序策略为
NONE,让组件严格按照你添加数据的顺序连线 - 先把所有数据点按对应的极角从小到大排序,保证连线沿着圆周方向走
- 手动设置XY轴的范围为对称等长,避免圆形被拉伸成椭圆
- 在数据序列末尾添加一个和起点坐标完全一致的点,实现路径闭合
修正后的可运行代码片段:
public void createScatterChart(){ final NumberAxis xAxis = new NumberAxis(); final NumberAxis yAxis = new NumberAxis(); // 计算半径最大值,设置对称坐标轴避免圆被拉伸 double maxRadius = Collections.max(this.r); xAxis.setAutoRanging(false); xAxis.setLowerBound(-maxRadius); xAxis.setUpperBound(maxRadius); yAxis.setAutoRanging(false); yAxis.setLowerBound(-maxRadius); yAxis.setUpperBound(maxRadius); final SmoothedChart<Number,Number> smoothedChart = new SmoothedChart<>(xAxis, yAxis); // 核心配置:关闭默认按X轴排序的连线逻辑,按数据添加顺序连线 smoothedChart.setAxisSortingPolicy(LineChart.SortingPolicy.NONE); XYChart.Series<Number, Number> circleSeries = new XYChart.Series<>(); // 先把所有点按极角从小到大排序,确保连线沿圆周延伸 List<Integer> sortedIndex = IntStream.range(0, this.nodes.size()) .boxed() .sorted(Comparator.comparingDouble(i -> this.nodes.get(i))) .collect(Collectors.toList()); for (int idx : sortedIndex) { double radian = Math.toRadians(this.nodes.get(idx)); double currentR = this.r.get(idx); circleSeries.getData().add(new XYChart.Data<>( currentR * Math.cos(radian), currentR * Math.sin(radian) )); } // 追加和起点完全一致的终点,让圆形路径闭合 int firstIdx = sortedIndex.get(0); double startRadian = Math.toRadians(this.nodes.get(firstIdx)); double startR = this.r.get(firstIdx); circleSeries.getData().add(new XYChart.Data<>( startR * Math.cos(startRadian), startR * Math.sin(startRadian) )); smoothedChart.getData().add(circleSeries); Stage stage = new Stage(); Scene scene = new Scene(smoothedChart,800,600); stage.setScene(scene); stage.show(); }
补充提示:如果你不需要平滑曲线效果,直接把
SmoothedChart换成JavaFX原生的LineChart即可,可以避免平滑算法在点密度不足时出现的曲线偏移问题;如果只是单纯需要画圆形不需要图表交互,直接用Circle节点绘制性能会高很多。
内容的提问来源于stack exchange,提问作者Demonxus
相关产品推荐
相关产品推荐

