[英]JavaFX Chart Series ConcurrentModificationException
我正在JavaFX上构建遗传算法,并且我想要一张图表来更新每一代的平均值和最大值。 我有一个按钮,可以执行20代,每次迭代都会更新图形,同时还会更新进度条。
以前的代码比较简单,没有所有重复项和引用。 这些只是关于如何避免异常的想法。 但是没有任何效果
我的意思是,我什至不迭代或删除某些内容。 这只是添加。
我得到这个例外:
Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1042)
at javafx.scene.chart.AreaChart.layoutPlotChildren(AreaChart.java:451)
at javafx.scene.chart.XYChart.layoutChartChildren(XYChart.java:731)
at javafx.scene.chart.Chart$1.layoutChildren(Chart.java:94)
at javafx.scene.Parent.layout(Parent.java:1079)
at javafx.scene.Parent.layout(Parent.java:1085)
at javafx.scene.Parent.layout(Parent.java:1085)
at javafx.scene.Parent.layout(Parent.java:1085)
at javafx.scene.Scene.doLayoutPass(Scene.java:552)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2397)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$31(Toolkit.java:348)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:347)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:374)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$405(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$149(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
这是准备
public void prepareChart() {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
final AreaChart<Number, Number> graph = new AreaChart<Number, Number>(xAxis, yAxis);
graph.setCreateSymbols(false);
graph.setTitle("Fitness - Generations relation");
graph.getXAxis().setLabel("Generations");
graph.getYAxis().setLabel("Fitness");
final Series<Number, Number> averageFitness = new XYChart.Series<Number, Number>();
averageFitness.setName("Average fitness");
final Series<Number, Number> maximumFitness = new XYChart.Series<Number, Number>();
maximumFitness.setName("Maximum fitness");
graph.getData().addAll(averageFitness, maximumFitness);
graphBox.getChildren().add(graph);
graphRef = graph;
}
这是我添加数据的方式
public void addData(double avgFitness, double maxFitness) {
final Series<Number, Number> averageFitness = graphRef.getData().get(0);
final Series<Number, Number> maximumFitness = graphRef.getData().get(1);
averageFitness.getData().add(new XYChart.Data<Number, Number>(generation, avgFitness));
maximumFitness.getData().add(new XYChart.Data<Number, Number>(generation, maxFitness));
generation++;
}
这是单击按钮时发生的情况
public void twentyGenerationsPressed() {
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws InterruptedException {
for (int i = 1; i <= 20; i++) {
disableButtons();
solver.nextGeneration();
updateProgress(i, 20);
executor.execute(() -> {
addData(solver.getAverage(), solver.getCurrentBest().getFitness());
});
}
return null;
}
};
task.setOnSucceeded(e -> {
updateLabels();
enableButtons();
});
progressBar.progressProperty().bind(task.progressProperty());
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
根据经验,无论何时修改JavaFX对象的内容,都应在JavaFX Application Thread上执行。
替换为:
executor.execute(() -> {
addData(solver.getAverage(), solver.getCurrentBest().getFitness());
});
有了这个:
final double avg = solver.getAverage();
final double best = solver.getCurrentBest().getFitness();
Platform.runLater(new Runnable() {
@Override
public void run() {
addData(avg, best);
}
});
尝试更新Timeline
动画中的图形。
Timeline timeline = new Timeline();
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(100), evt -> addData(...)));
timeline.setCycleCount(20);
button.setOnAction(e -> timeline.play());
时间轴的好处是,您可以指定两次更新之间的持续时间,我在您的代码中看不到
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.