2017-09-14 78 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")); 
    } 
}); 

要小心,這樣做時不會導致級聯無限循環的更改。