问题描述
我想在LineChart中设置一些值,但是我遇到了一个错误:添加了重复的序列或NPE(我尝试在序列表中clear
调用retainAll
,但没有帮助)在我的控制器类中,我存储了chart
实例
I want to set some values into LineChart but Ive got an error: Duplicate series added, or NPE (I try to clear
my series list, calling retainAll
but nothing helps) In my controller class Ive stored my chart
instance
public static void loadToJSON(LocalDate startDate,LocalDate endDate,Controller controller) {
Task<Integer> task = new Task<Integer>() {
@Override protected Integer call() throws Exception {
double MIN_VAL=Double.MAX_VALUE;
double MAX_VALUE=Double.MIN_VALUE;
XYChart.Series<String,Number> series = new XYChart.Series<String,Number>();
for (LocalDate date = startDate;
!date.isEqual(endDate.plusDays(1));
date = date.plusDays(1)) {
String formattedDate = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
URLConnection urlCon = null;
String baseURL="http://api.fixer.io/";
try {
URL url = new URL(baseURL+formattedDate+"?symbols=PLN,EUR");
urlCon = url.openConnection();
InputStreamReader in = new InputStreamReader(urlCon.getInputStream());
ObjectMapper mapper = new ObjectMapper();
ExchangeRate jsonObject = mapper.readValue(in, ExchangeRate.class);
if(MIN_VAL>jsonObject.getRates().get("PLN"))
MIN_VAL=jsonObject.getRates().get("PLN");
if(MAX_VALUE<jsonObject.getRates().get("PLN"))
MAX_VALUE=jsonObject.getRates().get("PLN");
in.close();
series.getData().clear();
series.getData().add(new XYChart.Data<String,Number>(formattedDate,jsonObject.getRates().get("PLN")));
controller.chart.getData().add(series);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
controller.messageBox.setText("Best exchange rate : "+MIN_VAL + " \nWorst exchange rate : "+MAX_VALUE);
return null;
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
推荐答案
您正在通过调用
controller.chart.getData().add(series);
在循环内.这将导致您描述的异常("java.lang.IllegalArgumentException:添加了重复的序列").
inside the loop. This will cause the exception you describe (" java.lang.IllegalArgumentException: Duplicate series added").
相反,您应该在循环开始之前添加一次序列,然后在循环内向其中添加数据.
Instead you should add the series once, before the beginning of the loop, and then add data to it inside the loop.
您还违反了JavaFX的线程规则,因为您正在从后台线程修改图表.只能从JavaFX Application Thread访问UI.因此,您应该在Platform.runLater(...)
中将用于修改图表(以及添加到图表中的系列)的调用包装在Platform.runLater(...)
中:
You are also violating the threading rules of JavaFX, because you are modifying the chart from a background thread. The UI can only be accessed from the JavaFX Application Thread. So you should wrap the calls that modify the chart (and the series, once it is added to the chart) in Platform.runLater(...)
:
public static void loadToJSON(LocalDate startDate, LocalDate endDate, Controller controller) {
Task<Integer> task = new Task<Integer>() {
@Override
protected Integer call() throws Exception {
double MIN_VAL = Double.MAX_VALUE;
double MAX_VALUE = Double.MIN_VALUE;
XYChart.Series<String, Number> series = new XYChart.Series<String, Number>();
Platform.runLater(() -> controller.chart.getData().add(series));
for (LocalDate date = startDate; !date.isEqual(endDate.plusDays(1)); date = date.plusDays(1)) {
String formattedDate = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
URLConnection urlCon = null;
String baseURL = "http://api.fixer.io/";
try {
URL url = new URL(baseURL + formattedDate + "?symbols=PLN,EUR");
urlCon = url.openConnection();
InputStreamReader in = new InputStreamReader(urlCon.getInputStream());
ObjectMapper mapper = new ObjectMapper();
ExchangeRate jsonObject = mapper.readValue(in, ExchangeRate.class);
if (MIN_VAL > jsonObject.getRates().get("PLN"))
MIN_VAL = jsonObject.getRates().get("PLN");
if (MAX_VALUE < jsonObject.getRates().get("PLN"))
MAX_VALUE = jsonObject.getRates().get("PLN");
in.close();
// Not sure why you are doing this?
// series.getData().clear();
Plaform.runLater(() ->
series.getData().add(new XYChart.Data<String, Number>(formattedDate, jsonObject.getRates().get("PLN"))));
// controller.chart.getData().add(series);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Platform.runLater(() ->
controller.messageBox.setText("Best exchange rate : " + MIN_VAL + " \nWorst exchange rate : " + MAX_VALUE));
return null;
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
这篇关于将数据动态添加到LineChart JavaFX的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!