【问题标题】:ConcurrentModificationException JavaFX [duplicate]ConcurrentModificationException JavaFX [重复]
【发布时间】:2017-07-20 19:02:22
【问题描述】:

我在 javaFX GUI 上遇到了这个问题......我想当我按下按钮时验证是否没有空窗格,否则我添加一个新窗格......但每次我得到 ConcurrentModificationException 。我试过打印,我看到这里只执行了 for 的第一部分,而不是其他部分

enter code here
    button.setOnAction(new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent event) {
                        for (Node node : vbox.getChildren()) {
                            if (node instanceof Pane){
                                Pane pane = (Pane) node ;
                                if (pane.getChildren().isEmpty()){
                                    vbox.getChildren().remove(node);
                                }
                            }``
                        }
                        drugrow drug = new drugrow();
                        vbox.getChildren().addAll(drug.getPane());
                    }
                });

【问题讨论】:

  • 调用 Platform.runlater 将在未来或多或少未指定的点删除节点,并为您要删除的每个节点创建一个 Runnable。
  • @SedrickJefferson Platform.runLater(...) 用于在后台线程上执行当前代码时在 FX 应用程序线程上执行代码块。这个问题与线程无关。这实际上在这种情况下有效(因为Platform.runLater(...) 恰好在从 FX 应用程序线程调用时实现)但充其量只是一个 hack。
  • 感谢您的信息。我一直都做错了。

标签: java multithreading javafx


【解决方案1】:

您在 for 每个循环中迭代 vbox 的子节点列表,同时从循环主体中的该列表中删除节点。然后迭代器通知列表状态发生了变化,因此抛出ConcurrentModificationException,因为它无法跟踪变化并保证迭代以有序的方式发生。这种迭代器称为快速失败迭代器。

更好的方法是收集要删除的节点,并在完成对列表的迭代后将其删除。

button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                final List<Node> removalCandidates = new ArrayList<>();
                for (Node node : vbox.getChildren()) {
                    if (node instanceof Pane){
                        Pane pane = (Pane) node ;
                        if (pane.getChildren().isEmpty()){
                            removalCandidates.add(node);
                        }
                    }
                }
                vbox.getChildren().removeAll(removalCandidates);
                drugrow drug = new drugrow();
                vbox.getChildren().addAll(drug.getPane());
            }
        });

【讨论】:

  • 或者,更简单地说,vbox.getChildren().removeIf(node -&gt; node instanceof Pane &amp;&amp; ((Pane)node).getChildren().isEmpty);
猜你喜欢
  • 2021-07-01
  • 2016-12-23
  • 2011-03-12
  • 2019-12-26
  • 1970-01-01
  • 2013-06-04
  • 2010-12-07
  • 2014-09-01
  • 2013-09-26
相关资源
最近更新 更多