I want to populate a line chart with data from the database. To achieve this, I created a class that returns an ObservableList<XYChart.Series>. But I struggle to merge the same XYChart.Series name (Like the example below).
MVCE
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Sample extends Application {
@Override public void start(Stage stage) {
//create the chart
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Year");
final LineChart<String,Number> lineChart =
new LineChart<>(xAxis, yAxis);
lineChart.setTitle("Employment Monitoring, 2020");
for(XYChart.Series series : getData()){
lineChart.getData().add(series);
}
// show the scene.
Scene scene = new Scene(lineChart, 800, 600);
stage.setScene(scene);
stage.show();
}
/* How can I return the right value to the line chart ? */
private ObservableList<XYChart.Series> getData(){
var list = FXCollections.<XYChart.Series>observableArrayList();
// Supposed that this data where values retrieved from the database
ArrayList<List> arrayList = new ArrayList<>();
arrayList.add(Arrays.asList("Permanent", "2011", 5));
arrayList.add(Arrays.asList("Job Order", "2011", 16));
arrayList.add(Arrays.asList("Permanent", "2012", 10));
arrayList.add(Arrays.asList("Job Order", "2012", 19));
for (List obs : arrayList){
list.add(
new XYChart.Series(
(String) obs.get(0),
FXCollections.observableArrayList(
new XYChart.Data<>((String) obs.get(1), (Number) obs.get(2))
)
));
}
return list;
}
public static void main(String[] args) { launch(args); }
}
As you have noticed, there are duplicate series for Permanent
and Job Order
Question is
How will I merge that duplicate entry so that I can achieve the output below?
without using a model class
EDIT
As @kleopatra said, (Based from my current knowledge on java) I tried to filter the data from the list by :
for (XYChart.Series series : getData()){
XYChart.Data item = (XYChart.Data) series.getData().get(0);
if (lineChart.getData().size() > 0){
for (XYChart.Series duplicate : lineChart.getData())
{
if (duplicate.getName().equals(series.getName()))
{
duplicate.getData().add(item);
} else {
// lineChart.getData().add(series);
}
}
} else {
lineChart.getData().add(series);
}
}
instead of just :
for(XYChart.Series series : getData())
{
lineChart.getData().add(series);
}
though it gives me the concatenated output for the Permanent
series (which is what I want to achieve). I can hardly add another series e.g. Job Order
to the line chart. As when I uncomment the code under else
condition. I got an error.
ConcurrentModificationException
Using @kleopatra's ideas, you can filter the list and create the
Series
using the filtered data. Your requirements complicate things.Arrays.asList("Permanent", "2011", 5)
also complicates things. It's bad practice inJava
to create aList
of different types. In my example, I used aHashMap
to filter the data.