Javafx上带有每个系列复选框的面积图

Javafx上带有每个系列复选框的面积图,java,checkbox,javafx,Java,Checkbox,Javafx,我有一个面积图,带有一些复选框,可以选择要在面积图上显示的系列。问题是我有以下错误: Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Duplicate series added 这是当3个复选框之一更改其值时执行的代码 /**AreaChart<Integer,Double> multipleGraphic; * CheckBox Hear

我有一个面积图,带有一些复选框,可以选择要在面积图上显示的系列。问题是我有以下错误:

Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Duplicate series added
这是当3个复选框之一更改其值时执行的代码

   /**AreaChart<Integer,Double> multipleGraphic;
        * CheckBox HeartRateCheck,PedalingRateCheck,AverageSpeedCheck;
        * XYChart.Series AvSpeed = new XYChart.Series();
        * XYChart.Series Cadence = new XYChart.Series();
        * XYChart.Series HeartRate = new XYChart.Series();
        **/


    private void setMultiGraph() {

            multipleGraphic.getData().removeAll(multipleGraphic.getData());
            multipleGraphic.getData().clear();

            if (HeartRateCheck.isSelected() && PedalingRateCheck.isSelected() && AverageSpeedCheck.isSelected()) {
                multipleGraphic.getData().addAll(AvSpeed, Cadence, HeartRate);
            }

            if (!HeartRateCheck.isSelected() && PedalingRateCheck.isSelected() && AverageSpeedCheck.isSelected()) {

                multipleGraphic.getData().addAll(AvSpeed, Cadence);
            }
            if (HeartRateCheck.isSelected() && !PedalingRateCheck.isSelected() && AverageSpeedCheck.isSelected()) {

                multipleGraphic.getData().addAll(AvSpeed, HeartRate);
            }
            if (HeartRateCheck.isSelected() && PedalingRateCheck.isSelected() && !AverageSpeedCheck.isSelected()) {

                multipleGraphic.getData().addAll(Cadence, HeartRate);
            }

            if (!HeartRateCheck.isSelected() && !PedalingRateCheck.isSelected() && AverageSpeedCheck.isSelected()) {

                multipleGraphic.getData().addAll(AvSpeed);
            }
            if (!HeartRateCheck.isSelected() && PedalingRateCheck.isSelected() && !AverageSpeedCheck.isSelected()) {

                multipleGraphic.getData().addAll(Cadence);
            }
            if (HeartRateCheck.isSelected() && !PedalingRateCheck.isSelected() && !AverageSpeedCheck.isSelected()) {

                multipleGraphic.getData().addAll(HeartRate);
            }
        }

谢谢。

根据需要,使用复选框选定的属性更改侦听器从图表中添加或删除序列

private void addSeriesListener(BooleanProperty selected, final XYChart.Series series) {
    selected.addListener((observable, wasSelected, isSelected) -> {
        if (isSelected) {
            chart.getData().add(series);
        } else {
            chart.getData().remove(series);
        }
    });
}
. . .
addSeriesListener(heartRateCheck.selectedProperty(), heartRateSeries);
addSeriesListener(cadenceCheck.selectedProperty(), cadenceSeries);
addSeriesListener(speedCheck.selectedProperty(), speedSeries);
完整示例应用程序


快速添加/删除系列时,此解决方案失败。我想有一些背景工作正在进行,所以添加/删除操作系统系列是异步的。。。?关于如何解决这个问题有什么想法吗?JavaFX是一个同步框架,所以像您描述的任何问题都将是一个奇怪的错误,并且会因为不同的原因出现。您可以尝试关闭图表的动画,看看是否适合您。如果你认为这是一个平台错误,你也可以在bugreport.java.com上提交错误;将解决此问题。我已尝试关闭动画,但问题仍然存在抱歉,我无法复制您在关闭jdk8u60动画时遇到的问题。
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.collections.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.util.Random;

public class AreaChartSample extends Application {
    private static final String HEART_RATE = "Heart Rate";
    private static final String PEDALING_RATE = "Pedaling Rate";
    private static final String AVERAGE_SPEED = "Average Speed";

    private Random random = new Random(42);

    private NumberAxis xAxis = new NumberAxis();
    private NumberAxis yAxis = new NumberAxis();
    private AreaChart<Number, Number> chart = new AreaChart<>(xAxis, yAxis);

    private XYChart.Series<Integer, Double> heartRateSeries = new XYChart.Series<>(
            HEART_RATE, randomData(10)
    );
    private XYChart.Series<Integer, Double> cadenceSeries = new XYChart.Series<>(
            PEDALING_RATE, randomData(50)
    );
    private XYChart.Series<Integer, Double> speedSeries = new XYChart.Series<>(
            AVERAGE_SPEED, randomData(100)
    );

    private CheckBox heartRateCheck = new CheckBox(HEART_RATE);
    private CheckBox cadenceCheck = new CheckBox(PEDALING_RATE);
    private CheckBox speedCheck = new CheckBox(AVERAGE_SPEED);

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

    @Override
    public void start(Stage stage) {
        HBox controls = new HBox(10, heartRateCheck, cadenceCheck, speedCheck);
        addSeriesListener(heartRateCheck.selectedProperty(), heartRateSeries);
        addSeriesListener(cadenceCheck.selectedProperty(), cadenceSeries);
        addSeriesListener(speedCheck.selectedProperty(), speedSeries);
        heartRateCheck.selectedProperty().set(true);
        cadenceCheck.selectedProperty().set(true);
        speedCheck.selectedProperty().set(true);

        chart.setTitle("Cycling");
        VBox layout = new VBox(10, chart, controls);
        layout.setPadding(new Insets(10));
        controls.setAlignment(Pos.CENTER);

        stage.setScene(new Scene(layout));
        stage.show();
    }

    private ObservableList<XYChart.Data<Integer, Double>> randomData(
            double offset
    ) {
        ObservableList<XYChart.Data<Integer, Double>> data = FXCollections.observableArrayList();

        for (int x = 0; x < 225; x++) {
            double y = random.nextDouble() * 30 + offset;
            data.add(new XYChart.Data<>(x, y));
        }

        return data;
    }

    @SuppressWarnings("unchecked")
    private void addSeriesListener(BooleanProperty selected, final XYChart.Series series) {
        selected.addListener((observable, wasSelected, isSelected) -> {
            if (isSelected) {
                chart.getData().add(series);
            } else {
                chart.getData().remove(series);
            }
        });
    }
}