A DESCRIPTION OF THE PROBLEM :
Using series.setData with a new list containing extra chart data breaks chart display:
- lines between data points disappear
- resizing chart leaves some data points on the same place, while others are moving
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run executable test case
2. Click button "Add Chart data"
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Lines in the line chart don't disappear, a new data point is added. When resizing the window, all data points are moving to their positions on the chart.
ACTUAL -
Lines and some points getting removed. Resizing the window makes some points move while other stay where they were.
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class LineChartRepro extends Application {
public void start(Stage stage) throws Exception {
LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());
XYChart.Series<Number, Number> series = new XYChart.Series<>();
series.setData(FXCollections.observableList(Arrays.asList(
new XYChart.Data<>(0,0),
new XYChart.Data<>(1,1))));
chart.getData().setAll(Collections.singletonList(series));
Button addChartData = new Button("Add Chart data");
addChartData.setOnAction(e -> {
ArrayList<XYChart.Data<Number, Number>> newList = new ArrayList<>(series.getData());
newList.add(new XYChart.Data<>(newList.size(), newList.size()));
series.setData(FXCollections.observableList(newList));
});
stage.setScene(new Scene(new VBox(chart, addChartData)));
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Instead of setting series data one could use observable list and modify that:
ObservableList<XYChart.Data<Number, Number>> data = FXCollections.observableList(new ArrayList<>());
data.add(new XYChart.Data<>(0,0));
data.add(new XYChart.Data<>(1,1));
series.setData(data);
...
addChartData.setOnAction(e -> {
data.add(new XYChart.Data<>(data.size(), data.size()));
});
Unfortunately, that's not a workaround for my use case. I'm the author of cljfx â https://github.com/cljfx/cljfx â a react-like wrapper of JavaFX that uses immutable values instead of observable cells for reactivity, so I need to use setters.
FREQUENCY : always
Using series.setData with a new list containing extra chart data breaks chart display:
- lines between data points disappear
- resizing chart leaves some data points on the same place, while others are moving
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run executable test case
2. Click button "Add Chart data"
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Lines in the line chart don't disappear, a new data point is added. When resizing the window, all data points are moving to their positions on the chart.
ACTUAL -
Lines and some points getting removed. Resizing the window makes some points move while other stay where they were.
---------- BEGIN SOURCE ----------
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class LineChartRepro extends Application {
public void start(Stage stage) throws Exception {
LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());
XYChart.Series<Number, Number> series = new XYChart.Series<>();
series.setData(FXCollections.observableList(Arrays.asList(
new XYChart.Data<>(0,0),
new XYChart.Data<>(1,1))));
chart.getData().setAll(Collections.singletonList(series));
Button addChartData = new Button("Add Chart data");
addChartData.setOnAction(e -> {
ArrayList<XYChart.Data<Number, Number>> newList = new ArrayList<>(series.getData());
newList.add(new XYChart.Data<>(newList.size(), newList.size()));
series.setData(FXCollections.observableList(newList));
});
stage.setScene(new Scene(new VBox(chart, addChartData)));
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Instead of setting series data one could use observable list and modify that:
ObservableList<XYChart.Data<Number, Number>> data = FXCollections.observableList(new ArrayList<>());
data.add(new XYChart.Data<>(0,0));
data.add(new XYChart.Data<>(1,1));
series.setData(data);
...
addChartData.setOnAction(e -> {
data.add(new XYChart.Data<>(data.size(), data.size()));
});
Unfortunately, that's not a workaround for my use case. I'm the author of cljfx â https://github.com/cljfx/cljfx â a react-like wrapper of JavaFX that uses immutable values instead of observable cells for reactivity, so I need to use setters.
FREQUENCY : always