2017-09-14 57 views
0

当我将监听器附加到observable列表并且在该监听器中时,我尝试删除一些元素,在某些情况下它会通过,并且在某些情况下会崩溃。JavaFX ObservableList删除监听器中的元素引发异常

场景: 项目从列表中删除。它会触发监听器,并在该监听器中尝试删除另一个项目。

  1. 如果在侦听器中,我尝试删除刚刚删除的不仅仅是下一个元素,而是工作正常。
  2. 如果在侦听器中,我尝试删除最初删除的元素,它会随着UnsupportedOperationException!崩溃!

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

我知道你可以同时删除两个,但问题是在侦听器中我需要检测哪些项目我需要删除,所以我删除我在那里。

这是ObservableList中的错误吗?

我希望它总是能够工作,或者至少总是会崩溃。

下面是代码示例:

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); 
    } 

} 
+5

[更改文档](https://docs.oracle.com/javase/8/javafx/api/javafx/collections/ListChangeListener.Change.html)用粗体显示:“源列表不能在侦听器中修改”。 – jewelsea

+0

谢谢!令人困惑的是,如果你不删除后续项目,它确实可以正常工作。 –

回答

2

ListChangeListener.Change文档指出:

源列表不能在监听器里修改

您可以解决此使用左右调用以调度要执行的其他更改编辑在未来的某个时间:

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

要小心,这样做时不会导致级联无限循环的更改。