Как получить серию из двух других серий? - PullRequest
0 голосов
/ 21 мая 2019

Я строю XYChart в JavaFX.Он содержит две серии (серии 1 и 2) и третью серию (серии 3), значения которых должны быть суммой серий 1 и 2.

Теперь серия 3 должна автоматически обновляться, если изменяются значения (добавляются, удаление, замена и т. д.) серии 1 или 2.

Каков наилучший способ добиться этого?

Заранее спасибо.

package lineChart;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;

public class LineChartSample extends Application {

    @Override
    public void start(Stage stage) {
        final NumberAxis xAxis = new NumberAxis();
        final NumberAxis yAxis = new NumberAxis();
        final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);

        XYChart.Series series1 = new XYChart.Series();


        series1.getData().add(new XYChart.Data(1, 10));
        series1.getData().add(new XYChart.Data(10, 20));
        series1.getData().add(new XYChart.Data(20, 30));
        lineChart.getData().add(series1);

        XYChart.Series series2 = new XYChart.Series();
        series2.getData().add(new XYChart.Data(1, 20));
        series2.getData().add(new XYChart.Data(10, 30));
        series2.getData().add(new XYChart.Data(20, 40));
        lineChart.getData().add(series2);

        XYChart.Series series3 = new XYChart.Series();
        // series3 = series1 + series2
        series3.getData().add(new XYChart.Data(1, 10 + 20));
        series3.getData().add(new XYChart.Data(10, 20 + 30));
        series3.getData().add(new XYChart.Data(20, 30 + 40));
        lineChart.getData().add(series3);



        Scene scene = new Scene(lineChart, 800, 600);
        stage.setScene(scene);
        stage.show();

    }

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

Обновление 1 Я обновил примеркод.Если я запускаю этот код, серия 3 реагирует на добавление или удаление объектов данных из серии 1 или серии 2. Но, к сожалению, он не реагирует на изменение значений объектов данных.

import javafx.application.Application;
import javafx.collections.ListChangeListener;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.stage.Stage;

public class LineChartSample extends Application {

    private static int updateCounter = 1;

    private XYChart.Series<Integer, Integer> series1, series2, series3;

    @Override
    public void start(Stage stage) {

        final NumberAxis xAxis = new NumberAxis();
        final NumberAxis yAxis = new NumberAxis();
        final LineChart<Integer, Integer> lineChart = new LineChart(xAxis, yAxis);

        series1 = new XYChart.Series<>();
        series1.getData().add(new XYChart.Data(1, 10));
        series1.getData().add(new XYChart.Data(10, 20));
        series1.getData().add(new XYChart.Data(20, 30));
        lineChart.getData().add(series1);

        series2 = new XYChart.Series<>();
        series2.getData().add(new XYChart.Data(1, 20));
        series2.getData().add(new XYChart.Data(10, 30));
        series2.getData().add(new XYChart.Data(20, 40));
        lineChart.getData().add(series2);

        series3 = new XYChart.Series<>();
        lineChart.getData().add(series3);
        bindDataSeieses();

        Scene scene = new Scene(lineChart, 800, 600);
        stage.setScene(scene);
        stage.show();

        // update 1
        updateSumSeries();
        // update 2
        series1.getData().remove(0);
        // update 3
        series1.getData().add(new XYChart.Data(1, 50));
        // No update :-(
        series1.getData().get(0).setYValue(200);

    }

    private void bindDataSeieses() {

        series1.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
        series2.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());

    }

    private void updateSumSeries() {

        System.out.println("Update " + updateCounter++);
        // todo enhance to support series of different length
        if (series1.getData().size() != series2.getData().size())
            return;
        series3.getData().clear();
        for (int index = 0; index < series1.getData().size(); index++) {

            int xValue = series1.getData().get(index).getXValue();
            int yValue = series1.getData().get(index).getYValue() + series2.getData().get(index).getYValue();
            series3.getData().add(new Data<>(xValue, yValue));
        }
    }

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

1 Ответ

0 голосов
/ 22 мая 2019

Вы можете добиться динамического обновления серии 3ed, добавив слушателей к двум другим:

import javafx.application.Application;
import javafx.collections.ListChangeListener;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.stage.Stage;

public class LineChartSample extends Application {

    private  XYChart.Series<Integer, Integer> series1, series2, series3;
    @Override
    public void start(Stage stage) {

        final NumberAxis xAxis = new NumberAxis();
        final NumberAxis yAxis = new NumberAxis();
        final LineChart<Integer, Integer> lineChart = new LineChart(xAxis, yAxis);
        series1 = new XYChart.Series<>();
        series1.getData().add(new XYChart.Data(1, 10));
        series1.getData().add(new XYChart.Data(10, 20));
        series1.getData().add(new XYChart.Data(20, 30));
        lineChart.getData().add(series1);

        series2 = new XYChart.Series<>();
        series2.getData().add(new XYChart.Data(1, 20));
        series2.getData().add(new XYChart.Data(10, 30));
        series2.getData().add(new XYChart.Data(20, 40));
        lineChart.getData().add(series2);

        series3 = new XYChart.Series<>();
        lineChart.getData().add(series3);
        bindDataSeieses();

        Scene scene = new Scene(lineChart, 800, 600);
        stage.setScene(scene);
        stage.show();
    }

    private void bindDataSeieses() {

        series1.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
        series2.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());

        updateSumSeries();
    }

    private void updateSumSeries() {

        //todo enhance to support series of different length
        if(series1.getData().size() != series2.getData().size())
                        throw new IllegalArgumentException("series1 and series2 must be of same length");
        series3.getData().clear();
        for (int index = 0; index < series1.getData().size(); index++){

            int xValue = series1.getData().get(index).getXValue();
            //todo verify series1.getData().get(index).getXValue() == series2.getData().get(index).getXValue()
            int yValue = series1.getData().get(index).getYValue() + series2.getData().get(index).getYValue();
            series3.getData().add(new Data<>(xValue, yValue));
        }
    }

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

Редактировать: ответ на обновленный код:обновление 1 не нужно.updateSumSeries() вызывается слушателем.обновление 2 заставляет series1.getData().size() != series2.getData().size() быть правдой, поэтому IllegalArgumentException выбрасывается.Следите за своими исключениями.

Следующий код демонстрируется и редактируется одним нажатием кнопки:

public class LineChartSample extends Application {

    private  XYChart.Series<Integer, Integer> series1, series2, series3;
    @Override
    public void start(Stage stage) {

        final NumberAxis xAxis = new NumberAxis();
        final NumberAxis yAxis = new NumberAxis();
        final LineChart<Integer, Integer> lineChart = new LineChart(xAxis, yAxis);

        series1 = new XYChart.Series<>();

        series1.getData().add(new XYChart.Data(1, 10));
        series1.getData().add(new XYChart.Data(10, 20));
        series1.getData().add(new XYChart.Data(20, 30));
        lineChart.getData().add(series1);

        series2 = new XYChart.Series<>();
        series2.getData().add(new XYChart.Data(1, 20));
        series2.getData().add(new XYChart.Data(10, 30));
        series2.getData().add(new XYChart.Data(20, 40));
        lineChart.getData().add(series2);

        series3 = new XYChart.Series<>();
        lineChart.getData().add(series3);
        bindDataSeieses();

        BorderPane root = new BorderPane(lineChart);
        Button btn = new Button("Add");
        btn.setOnAction(e->series1.getData().set(0, new Data<>(1, 200)));
        root.setBottom(btn);
        Scene scene = new Scene(root, 800, 600);
        stage.setScene(scene);
        stage.show();
    }

    private void bindDataSeieses() {

        series1.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());
        series2.getData().addListener((ListChangeListener<Data<Integer, Integer>>) c -> updateSumSeries());

        updateSumSeries();
    }

    private void updateSumSeries() {

        //todo enhance to support series of different length
        if(series1.getData().size() != series2.getData().size())
            throw new IllegalArgumentException("series1 and series2 must be of same length");
        series3.getData().clear();
        for (int index = 0; index < series1.getData().size(); index++){

            int xValue = series1.getData().get(index).getXValue();
            //todo verify series1.getData().get(index).getXValue() == series2.getData().get(index).getXValue()
            int yValue = series1.getData().get(index).getYValue() + series2.getData().get(index).getYValue();
            series3.getData().add(new Data<>(xValue, yValue));
        }
    }

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