CategoryAxis(xAxis) 获取每个Category的位置

CategoryAxis (xAxis) get Position of each Category

我想在 CategoryAxis 上的每个类别之间添加一条线,问题是类别根据用户输入而变化,所以我需要在运行时添加它们,我通过扩展 CustomBarChart 并添加它们来实现在 seriesAdded() 上。

如何获得每个类别的位置 (xAxis) 以及每个类别的长度 (xAxis),以便计算在图形之间放置线的位置。

还没有找到获取每个类别宽度的方法。

使用 getDisplayPosition() 应该可以得到 Position,但将它用于此图表,例如给了我这些结果,但我似乎无法弄清楚它们与实际位置的关系。

4.545454545454546
3.6363636363636367
2.7272727272727275
1.8181818181818188
0.9090909090909096
8.881784197001252E-16
-0.9090909090909083
-1.8181818181818175
-2.7272727272727266
-3.636363636363636
-4.545454545454544

这是对想法的改编。它应该提供一个很好的起点。

package org.jamesd.examples.barchartwithlines;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.layout.BorderPane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

import java.io.IOException;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        CategoryAxis xAxis = new CategoryAxis();
        NumberAxis yAxis = new NumberAxis();
        BarChart<String, Number> chart = new BarChart<>(xAxis, yAxis) {
            private List<Line> lines = new ArrayList<>();
            @Override
            protected void layoutPlotChildren() {
                super.layoutPlotChildren();
                List<Series<String, Number>> data = getData();
                if (data.size() == 0) {
                    getPlotChildren().removeAll(lines);
                    lines.clear();
                    return ;
                }
                // assuming only one series
                Series<String, Number> series = data.get(0);
                int numLines = series.getData().size() - 1;
                // remove unused lines:
                for (int i = lines.size() - 1 ; i >= numLines ; i--) {
                    getPlotChildren().remove(lines.get(i));
                    lines.remove(i);
                }
                // create new lines:
                for (int i = lines.size() ; i < numLines ; i++) {
                    Line line = new Line();
                    lines.add(line);
                    getPlotChildren().add(line);
                }

                double[] catPositions = new double[numLines + 1];
                for (int i = 0 ; i < catPositions.length ; i++) {
                    Data<String, Number> d = series.getData().get(i);
                    catPositions[i] = xAxis.getDisplayPosition(d.getXValue());
                }
                Arrays.sort(catPositions);
                double startY = yAxis.getDisplayPosition(yAxis.getLowerBound());
                double endY = yAxis.getDisplayPosition(yAxis.getUpperBound());
                for (int i = 0 ; i < catPositions.length - 1 ; i++) {
                    Line line = lines.get(i);
                    double lineX = (catPositions[i] +  catPositions[i+1]) / 2 ;
                    line.setStartX(lineX);
                    line.setEndX(lineX);
                    line.setStartY(startY);
                    line.setEndY(endY);
                }
            }
        };

        Random rng = new Random();
        XYChart.Series<String, Number> series = new XYChart.Series<>();
        DateTimeFormatter format = DateTimeFormatter.ofPattern("LLL");
        for (Month month : Month.values()) {
            series.getData().add(new XYChart.Data<>(format.format(month), rng.nextDouble() * 100));
        }
        series.setName("2020");
        chart.getData().add(series);

        BorderPane root = new BorderPane(chart);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

这导致