簡體   English   中英

JavaFx和綁定XYChart.Series

[英]JavaFx and binding XYChart.Series

我在更新圖表時遇到了一些問題

我有 class 圖表

public class Chart {
    public LineChart<String, Number> createChart() {
        // defining the axes
        final CategoryAxis xAxis = new CategoryAxis(); // we are gonna plot against time
        final NumberAxis yAxis = new NumberAxis();
        xAxis.setLabel("Time/s");
        xAxis.setAnimated(false); // axis animations are removed
        yAxis.setLabel("Value");
        yAxis.setAnimated(false); // axis animations are removed

        // creating the line chart with two axis created above
        final LineChart<String, Number> lineChart = new LineChart<>(xAxis, yAxis);
        lineChart.setAnimated(false); // disable animations

        // defining a series to display data
        XYChart.Series<String, Number> series = new XYChart.Series<>();
        series.setName("Data Series");

        // add series to chart
        lineChart.getData().add(series);

        return lineChart;
    }
}

和主class

public class Main extends Application {
    final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
    private Service service;

    public static void main(String[] args) {
        launch(args);
    }


    @Override
    public void start(Stage primaryStage) throws Exception {

        primaryStage.setTitle("Hello World");
        primaryStage.setWidth(500);
        primaryStage.setHeight(500);

        Chart chart = new Chart();
        LineChart<String, Number> lineChart = chart.createChart();
        //   setup scene
        Scene scene = new Scene(lineChart, 800, 600);
        primaryStage.setScene(scene);

        createService();

        primaryStage.show();
        startService();

// First variant
Platform.runLater(() -> lineChart.getData().get(0).getData().add((XYChart.Data<String, Number>) service.valueProperty().getValue()));

//Second variant
lineChart.getData().get(0).getData().add((XYChart.Data<String, Number>) service.valueProperty().getValue());

//Third variant
lineChart.getData().get(0).dataProperty().bind(service.valueProperty());

    }

    private void createService() {

        service = new Service<ObservableList<XYChart.Data<String, Number>>>() {
            @Override
            protected Task<ObservableList<XYChart.Data<String, Number>>> createTask() {
                return new Task<ObservableList<XYChart.Data<String, Number>>>() {
                    Date now;
                    Integer random;

                    @Override
                    protected ObservableList<XYChart.Data<String, Number>> call() throws InterruptedException {
                        for (int i = 0; i < 10; i++) {
                            now = new Date();
                            random = ThreadLocalRandom.current().nextInt(10);

                            System.out.println(simpleDateFormat.format(now) + "  " + random);
                            updateValue(FXCollections.observableArrayList(new XYChart.Data(simpleDateFormat.format(now), random)));
                            Thread.sleep(500);
                        }
                        return FXCollections.observableArrayList(new XYChart.Data(simpleDateFormat.format(now), random));
                    }
                };
            }
        };


    }

    private void startService() {
        if (!service.isRunning()) {
            service.reset();
            service.start();
        }
    }
}

Main class 的第一個和第二個變體在線程“JavaFX 應用程序線程”java.lang.NullPointerException 中拋出異常異常並且不更新我的圖表,但第三個更新它但它更新了,但我需要為我的圖表添加新值形象的

如何更新我的代碼以將所有 10 個值添加到圖中,而不是僅添加 1 個或僅最后一個?

我不得不將我的主要 class 更改為

public class Main extends Application {
    final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
    private LineChart<String, Number> lineChart;

    public static void main(String[] args) {
        launch(args);
    }


    @Override
    public void start(Stage primaryStage) throws Exception {

        primaryStage.setTitle("Hello World");
        primaryStage.setWidth(500);
        primaryStage.setHeight(500);

        Chart chart = new Chart();
        lineChart = chart.createChart();
        //   setup scene
        Scene scene = new Scene(lineChart, 800, 600);
        primaryStage.setScene(scene);

        createService();

        primaryStage.show();

    }

    private void createService() {

        Task<Void> task = new Task<Void>() {
            Date now;
            Integer random;

            @Override
            protected Void call() throws InterruptedException {
                for (int i = 0; i < 10; i++) {
                    now = new Date();
                    random = ThreadLocalRandom.current().nextInt(10);

                    System.out.println(simpleDateFormat.format(now) + "  " + random);
                    Platform.runLater(() -> updateChart(now, random));
                    Thread.sleep(500);
                }
                return null;
            }
        };
        Thread thread = new Thread(task);
        thread.setDaemon(true);
        thread.start();
    }

    private void updateChart(Date now, Integer random) {
        lineChart.getData().get(0).getData().add(new XYChart.Data(simpleDateFormat.format(now), random));
    }

}
  1. 第一個變體

valueProperty.getValue()可能是 null 因為服務任務執行可能還沒有達到setValue調用。 但最重要的是這個演員陣容

Platform.runLater(() -> lineChart.getData().get(0).getData().add(/*here -->*/(XYChart.Data<String, Number>) service.valueProperty().getValue()));

沒有意義。 服務valueProperty類型為ObservableList<XYChart.Data<String, Number>>行中指定

service = new Service<ObservableList<XYChart.Data<String, Number>>>() 

如果您想添加當前服務值,您寧願使用ObservableList::addAll方法並將值轉換為列表類型:

Platform.runLater(() -> lineChart.getData().get(0).getData().addAll((ObservableList<XYChart.Data<String, Number>>)service.valueProperty().getValue()));

此外,由於您知道稍后將擁有什么類型的服務,您已經可以通過更改在聲明中指定其完整類型:

private Service service;

進入

private Service<ObservableList<XYChart.Data<String, Number>>> service;

結果只是:

Platform.runLater(() -> lineChart.getData().get(0).getData().addAll(service.getValue()));

  1. 第二種變體

與第一個變體的故事基本相同,但另外您不在 UI 線程上進行更改,因此這可能會在更新圖表時造成麻煩。


  1. 第三變體

您使用僅包含一個元素的列表覆蓋服務value

// each time new list!
updateValue(FXCollections.observableArrayList(new XYChart.Data(simpleDateFormat.format(now), random)));

在服務定義中,您應該創建一個列表,並且 append 指向該列表

private void createService() {
    service = new Service<ObservableList<XYChart.Data<String, Number>>>() {
        @Override
        protected Task<ObservableList<XYChart.Data<String, Number>>> createTask() {
            return new Task<ObservableList<XYChart.Data<String, Number>>>() {
                Date now;
                Integer random;
                // Specify ONE list
                ObservableList<XYChart.Data<String, Number>> data = FXCollections.observableArrayList();
                @Override
                protected ObservableList<XYChart.Data<String, Number>> call() throws InterruptedException {
                    updateValue(data);
                    for (int i = 0; i < 10; i++) {
                        now = new Date();
                        random = ThreadLocalRandom.current().nextInt(10);
                        System.out.println(simpleDateFormat.format(now) + "  " + random);
                        // Add points to the data (on UI thread to have chart updated properly!)
                        Platform.runLater(() -> data.add(new XYChart.Data(simpleDateFormat.format(now), random)));
                        Thread.sleep(500);
                    }
                    return data;
                }
            };
        }
    };
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM