How to add value marker to JavaFX chart?

I am trying to build a series of diagrams using JavaFX where data is inserted dynamically.

Every time a new value is inserted, I want to check if it is the highest value, and if so, I want to draw a horizontal line to show that this is the maximum value.

In a JFree chart, I would use ValueMarker, but I'm trying to do the same with JavaFX.

I tried using the Line object, but it is definitely not the same because I cannot provide Chart values, it takes the relative positions of the pixels in the windows.

Here is a screenshot of the chart I want to achieve:

http://postimg.org/image/s5fkupsuz/

Any suggestions? Thanks.

+7
source share
1 answer

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

Although these coordinates relate to the area of ​​the diagram, which you can recognize by the following code:

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

Note localToScene() method that allows you to convert any coordinates to Scene. This way you can use them to update the coordinates of the value marker. Make sure you make a call to localToScene after your scene has been shown.

See the sample program below, which creates the following diagram:

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(); } } 
+14
source

All Articles