侦听器中的JavaFX ObservableList remove元素引发异常 [英] JavaFX ObservableList remove element in listener throws exception

查看:635
本文介绍了侦听器中的JavaFX ObservableList remove元素引发异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我将侦听器附加到可观察列表时,在该侦听器中,我尝试删除某些元素,在某些情况下它会通过,在某些情况下会崩溃.

When I attach listener to observable list and in that listener I try to remove some element, in some cases it passes and in some cases it crashes.

场景: 项目已从列表中删除.它会触发侦听器,然后在该侦听器中尝试删除其他项.

Scenario: Item is removed from a list. It triggers listener, and in that listener I try to delete another item.

  1. 如果我在侦听器中尝试删除的元素不仅仅与最初删除的元素相邻,那么它可以正常工作.
  2. 如果我在侦听器中尝试删除刚开始删除的NEXT元素,则会因UnsupportedOperationException崩溃!
  1. If in listener I try to remove element that is not just next to initially removed, it works OK.
  2. If in listener I try to remove element that is JUST NEXT to initially removed, it crashes with UnsupportedOperationException!!!

有人有类似的问题吗?您有任何提示,建议或解决方法吗?

Did anybody had similar problem? Do you have any tips, suggestions or workaround?

我知道您可以同时删除两个项目,但是问题是在侦听器中,我需要检测哪些项目也需要删除,因此我要在其中删除我.

I know that you can delete both at the same time, but problem is that in listener I need to detect which items I need to remove also so I delete i there.

这是ObservableList中的错误吗?

Is this a bug in ObservableList?

我希望它总是可以正常工作,或者至少总是崩溃.

I would expect that it always work, or at least to always crash.

这是代码示例:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ListRemoveFromListener extends Application {

    boolean changing = false;

    @Override
    public void start(Stage primaryStage) throws Exception {
        VBox vbox = new VBox();

        Button buttonSuccess = new Button("remove success");
        buttonSuccess.setOnAction(e -> {
            removeSuccess();
        });

        Button buttonBreak = new Button("Remove breaks");
        buttonBreak.setOnAction(e -> {
            removeBreaks();
        });

        vbox.getChildren().addAll(buttonSuccess, buttonBreak);

        Scene scene = new Scene(vbox);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * If we try in listener to remove element just next to one that was
     * initially removed, exception is thrown.
     */
    private void removeBreaks() {
        ObservableList<String> list = FXCollections.observableArrayList();
        list.add("first");
        list.add("second");
        list.add("third");
        list.add("fourth");
        list.add("fifth");
        list.add("sixth");

        list.addListener(new ListChangeListener<String>() {

            @Override
            public void onChanged(Change<? extends String> c) {
                list.remove("second");
            }
        });

        list.remove("third");
    }

    /**
     * If we try in listener to remove element that is not just next to initially
     * removed element, element is removed and all works O.
     */
    private void removeSuccess() {
        ObservableList<String> list = FXCollections.observableArrayList();
        list.add("first");
        list.add("second");
        list.add("third");
        list.add("fourth");
        list.add("fifth");
        list.add("sixth");

        list.addListener(new ListChangeListener<String>() {

            @Override
            public void onChanged(Change<? extends String> c) {
                list.remove("fifth");
            }
        });

        list.remove("third");
    }

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

}

推荐答案

ListChangeListener.Change 文档状态:

无法在侦听器内部修改源列表

您可以使用 Platform.runLater 调用以计划在将来的某个时间执行的其他更改:

You can work around this using a Platform.runLater call to schedule the additional change to be performed at some time in the future:

list.addListener((ListChangeListener<String>) c -> {
    if (list.contains("second")) {
        Platform.runLater(() -> list.remove("second"));
    }
});

在执行此操作时要小心,以免引起级联的无限变化循环.

be careful when doing so that you don't cause a cascading infinite loop of changes.

这篇关于侦听器中的JavaFX ObservableList remove元素引发异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆