如何在不使用扩展的情况下用JavaFX创建箱线图并将箱体放入坐标轴中?
如何在不使用扩展的情况下用JavaFX创建箱线图并将箱体放入坐标轴中?
嘿,我来帮你搞定这个问题!其实不用扩展库,纯JavaFX就能做出箱线图,你之前用普通Pane放不进去,核心问题是普通布局的坐标系统和JavaFX坐标轴的坐标系统不匹配,得用专门的Chart容器来结合两者,下面给你一步步讲具体怎么做:
1. 先搭好坐标轴和Chart容器
JavaFX的NumberAxis(数值坐标轴)是和XYChart绑定设计的,所以我们先创建坐标轴,再用匿名子类实例化抽象的XYChart作为承载箱体的容器:
// 创建x轴(比如表示不同类别)和y轴(表示数值) NumberAxis xAxis = new NumberAxis(); NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("数据类别"); yAxis.setLabel("数值范围"); // 实例化XYChart(因为是抽象类,所以用匿名子类) XYChart<Number, Number> boxPlotChart = new XYChart<>(xAxis, yAxis) {};
2. 绘制箱体的核心:坐标转换
普通Pane的坐标是从左上角(0,0)开始的,但坐标轴的坐标是基于数据值的,所以我们需要用坐标轴的getDisplayPosition()方法,把数据值转换成Chart绘图区域内的像素坐标,这样画出来的图形才能精准对应到坐标轴上的位置。
举个具体例子,假设我们要在x轴的1这个位置画一个箱体,数据的统计值是:最小值5、下四分位Q1=10、中位数15、上四分位Q3=20、最大值25:
// 定义箱体宽度 double boxWidth = 60; // 获取x轴上类别1对应的像素位置 double xCenter = xAxis.getDisplayPosition(1); // 把y轴的各个统计值转换成像素坐标 double yMin = yAxis.getDisplayPosition(5); double yQ1 = yAxis.getDisplayPosition(10); double yMedian = yAxis.getDisplayPosition(15); double yQ3 = yAxis.getDisplayPosition(20); double yMax = yAxis.getDisplayPosition(25);
3. 绘制箱体的各个组件
箱线图由箱体、中位数线、须线和端点组成,用JavaFX的Rectangle和Line、Circle就能实现:
// 绘制箱体(注意y轴的像素坐标是从上到下递增的,所以高度是yQ1 - yQ3) Rectangle box = new Rectangle(xCenter - boxWidth/2, yQ3, boxWidth, yQ1 - yQ3); box.setFill(Color.LIGHTSTEELBLUE); box.setStroke(Color.BLACK); // 绘制中位数线 Line medianLine = new Line(xCenter - boxWidth/2, yMedian, xCenter + boxWidth/2, yMedian); medianLine.setStroke(Color.DARKRED); medianLine.setStrokeWidth(2); // 绘制上下须线 Line topWhisker = new Line(xCenter, yQ1, xCenter, yMin); Line bottomWhisker = new Line(xCenter, yQ3, xCenter, yMax); // 绘制最小值和最大值的端点 Circle minDot = new Circle(xCenter, yMin, 3); Circle maxDot = new Circle(xCenter, yMax, 3); minDot.setFill(Color.BLACK); maxDot.setFill(Color.BLACK);
4. 把组件添加到Chart中
不要把这些图形加到普通Pane里,而是加到XYChart的plotChildren集合里,这个集合专门用来存放Chart绘图区域的自定义元素:
boxPlotChart.getPlotChildren().addAll(box, medianLine, topWhisker, bottomWhisker, minDot, maxDot);
5. 最后显示Chart
把Chart放到BorderPane这类布局里,再放到Scene中显示即可:
BorderPane root = new BorderPane(boxPlotChart); Scene scene = new Scene(root, 800, 600); primaryStage.setTitle("纯JavaFX箱线图"); primaryStage.setScene(scene); primaryStage.show();
这样做出来的箱体就会准确显示在坐标轴对应的位置啦!如果要画多个箱体,只需要重复上面的步骤,改变x轴的位置(比如x=2、x=3)就行。
备注:内容来源于stack exchange,提问作者ceci055
相关产品推荐
相关产品推荐

