FULL PRODUCT VERSION : java version "1.8.0_60" Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows [Version 10.0.10240] A DESCRIPTION OF THE PROBLEM : The NumberAxis.autoRange method may enter an infinite loop if consecutive double values are added to a chart that are very close together. This is noticeable because the JavaFX thread will hang due to the infinite loop. The chart axis must have auto ranging enabled and NumberAxis.setForceZeroInRange(false). See attached minimal, complete, and verifiable example to repro. See http://stackoverflow.com/questions/32513409/javafx-numberaxis-autorange-infinite-loop STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Create LineChart 2. Create Y-Axis NumberAxis with auto range enable and setForceZeroInRange(false) 3. Add -20.98295609742171 to Y-Axis 4. Add -20.982956097421706 to Y-Axis EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - The JavaFX thread should not hang and the chart should continue to update. ACTUAL - The JavaFX thread hangs and the chart stops updating REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.util.*; import javafx.application.*; import javafx.concurrent.*; import javafx.scene.*; import javafx.scene.chart.*; import javafx.stage.*; import javafx.util.*; public class SmallTickUnitTest extends Application { @Override public void start(Stage stage) { final NumberAxis xAxis = new NumberAxis(); final NumberAxis yAxis = new NumberAxis(); final LineChart<Number, Number> lineChart = new LineChart<>(xAxis, yAxis); xAxis.setLabel("Time"); yAxis.setLabel("Data"); lineChart.setTitle("Measured Data"); XYChart.Series<Number, Number> series1 = new XYChart.Series<>(); series1.setName("Wind Speed"); lineChart.getData().addAll(series1); // If this is set to true then the bug will not occur yAxis.setForceZeroInRange(false); // Use two values that are extremely close together List<Double> values = Arrays.asList(-20.98295609742171, -20.982956097421706); final Iterator<Double> itr = values.iterator(); ScheduledService<XYChart.Data<Number, Number>> svc = new ScheduledService<XYChart.Data<Number, Number>>() { int time = 0; @Override protected Task<XYChart.Data<Number, Number>> createTask() { return new Task<XYChart.Data<Number, Number>>() { @Override protected XYChart.Data<Number, Number> call() { time++; return new XYChart.Data<>(time, itr.hasNext() ? itr.next() : 0); } }; } }; svc.setPeriod(Duration.seconds(2)); svc.setRestartOnFailure(true); svc.setOnSucceeded((WorkerStateEvent e) -> { XYChart.Data<Number, Number> value = svc.getLastValue(); if (value != null) { series1.getData().add(value); } }); Scene scene = new Scene(lineChart, 800, 600); stage.setTitle("Line Chart Sample"); stage.setScene(scene); stage.show(); svc.start(); } public static void main(String[] args) { launch(args); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Sanitize floating point chart input data such that values cannot be close to each other.
|