将数据动态添加到LineChart JavaFX [英] Dynamically adding data into LineChart JavaFX

查看:206
本文介绍了将数据动态添加到LineChart JavaFX的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆