How to add a value marker to JavaFX chart?

前端 未结 1 1863
后悔当初
后悔当初 2020-12-01 13:06

I am trying to build a series chart using JavaFX, where data is inserted dynamically.

Each time that a new value is inserted I would like to check if this is the hi

相关标签:
1条回答
  • 2020-12-01 13:57

    To convert chart values to pixels you can use method NumberAxis#getDisplayPosition() which return actual coordinates of the chart nodes.

    Although these coordinates are relative to chart area, which you can find out by next code:

    Node chartArea = chart.lookup(".chart-plot-background");
    Bounds chartAreaBounds = chartArea.localToScene(chartArea.getBoundsInLocal());
    

    Note localToScene() method which allows you to convert any coordinates to Scene ones. Thus you can use them to update your value marker coordinates. Make sure you make localToScene call after your Scene have been shown.

    See sample program below which produces next chart:

    enter image description here

    public class LineChartValueMarker extends Application {
    
        private Line valueMarker = new Line();
        private XYChart.Series<Number, Number> series = new XYChart.Series<>();
        private NumberAxis yAxis;
        private double yShift;
    
        private void updateMarker() {
            // find maximal y value
            double max = 0;
            for (Data<Number, Number> value : series.getData()) {
                double y = value.getYValue().doubleValue();
                if (y > max) {
                    max = y;
                }
            }
            // find pixel position of that value
            double displayPosition = yAxis.getDisplayPosition(max);
            // update marker
            valueMarker.setStartY(yShift + displayPosition);
            valueMarker.setEndY(yShift + displayPosition);
        }
    
        @Override
        public void start(Stage stage) {
            LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(0, 100, 10), yAxis = new NumberAxis(0, 100, 10));
    
            series.getData().add(new XYChart.Data(0, 0));
            series.getData().add(new XYChart.Data(10, 20));
    
            chart.getData().addAll(series);
            Pane pane = new Pane();
            pane.getChildren().addAll(chart, valueMarker);
            Scene scene = new Scene(pane);
    
            // add new value on mouseclick for testing
            chart.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent t) {
                    series.getData().add(new XYChart.Data(series.getData().size() * 10, 30 + 50 * new Random().nextDouble()));
                    updateMarker();
                }
            });
    
            stage.setScene(scene);
            stage.show();
    
            // find chart area Node
            Node chartArea = chart.lookup(".chart-plot-background");
            Bounds chartAreaBounds = chartArea.localToScene(chartArea.getBoundsInLocal());
            // remember scene position of chart area
            yShift = chartAreaBounds.getMinY();
            // set x parameters of the valueMarker to chart area bounds
            valueMarker.setStartX(chartAreaBounds.getMinX());
            valueMarker.setEndX(chartAreaBounds.getMaxX());
            updateMarker();
        }
    
        public static void main(String[] args) {
            launch();
        }
    }
    
    0 讨论(0)
提交回复
热议问题