Отобразить вертикальную линию в JavaFx BarChart - PullRequest
0 голосов
/ 26 октября 2018

Я использую JavaFx BarChart для отображения гистограммы, xAxis - это CategoryAxis, я хочу отобразить две вертикальные линии, соответствующие среднему значению и медиане, как показано на этой картинке

спасибо

1 Ответ

0 голосов
/ 26 октября 2018

Вы должны поместить свою диаграмму в Pane и добавить Lines как большее число дочерних элементов того же Pane.Тогда хитрость заключается в том, как найти, где нарисовать Lines: для этого вам нужно найти область диаграммы, используя поиск CSS (.lookup(".chart-plot-background");) и попросить ось диаграммы, где будет отображаться конкретное значение (Axis().getDisplayPosition()).Вот полный пример:

package so_52998721;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.geometry.Bounds;
import javafx.scene.Node;
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.Pane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

/**
 *
 * @author ced04u
 */
public class SO_52998721 extends Application {

    private XYChart<String, Number> barChart;
    final private Line horizontalLine = new Line();
    final private Line verticalLine = new Line();

    @Override
    public void start(Stage primaryStage) {

        Pane root = new Pane();
        barChart = new BarChart<>(
                new CategoryAxis(),
                new NumberAxis(0, 100, 5));

        root.getChildren().addAll(barChart, horizontalLine, verticalLine);

        barChart.setMaxWidth(Double.MAX_VALUE);
        barChart.prefWidthProperty().bind(root.widthProperty());
        barChart.prefHeightProperty().bind(root.heightProperty());

        //populate barchart with some data
        barChart.getData().add(new XYChart.Series(
                FXCollections.observableArrayList(new XYChart.Data("pizza", 80.0),
                        new XYChart.Data("spaghetti", 50.0),
                        new XYChart.Data("mozzarella", 30.0)
                )
        ));

        //lines have to be updated every time the chart size changes
        barChart.boundsInLocalProperty().addListener(new ChangeListener<Bounds>() {
            @Override
            public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
                Platform.runLater(() -> {
                    updateLines();
                });
            }
        });

        updateLines();

        Scene scene = new Scene(root, 1024, 768);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void updateLines() {

        // find chart area Node
        Node chartArea = barChart.lookup(".chart-plot-background");
        // remember scene position of chart area
        Bounds chartAreaBounds = chartArea.localToParent(chartArea.getBoundsInLocal());

        //******** horizontal line ******************
        horizontalLine.setStartX(chartAreaBounds.getMinX());
        horizontalLine.setEndX(chartAreaBounds.getMaxX());
        final double averageValue = (80 + 50 + 30) / 3;
        double yShift = chartAreaBounds.getMinY();
        // find pixel position of the specified value
        final double medianPosition = barChart.getYAxis().getDisplayPosition(averageValue);
        horizontalLine.setStartY(yShift + medianPosition);
        horizontalLine.setEndY(yShift + medianPosition);

        //******** vertical line ******************
        verticalLine.setStartY(chartAreaBounds.getMinY());
        verticalLine.setEndY(chartAreaBounds.getMaxY());
        double xShift = chartAreaBounds.getMinX();
        // find pixel position of the specified value
        final double mozzarellaPosition = barChart.getXAxis().getDisplayPosition("mozzarella");
        verticalLine.setStartX(xShift + mozzarellaPosition);
        verticalLine.setEndX(xShift + mozzarellaPosition);

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}
...