I created a simple application for testing filtered lists and their behavior when changing the corresponding list of sources. I would also like to test update changes, so I created an ObservableList from ObservableList s. This is faster and easier than creating an additional class, such as Person, which has observable fields.
The code looks like this:
ListChangeListener<ObservableList<String>> changeNotifier = new ListChangeListener<ObservableList<String>>() { @Override public void onChanged(Change<? extends ObservableList<String>> c) { while (c.next()) { if (c.wasPermutated()) { System.out.println("permutation"); } else if (c.wasUpdated()) { System.out.println("update"); } else { if (c.wasRemoved()) { System.out.println("remove"); } if (c.wasAdded()) { System.out.println("add"); } if (c.wasReplaced()) { System.out.println("replace"); } } } } }; Callback<ObservableList<String>, Observable[]> identityExtractor = new Callback<ObservableList<String>, Observable[]>() { @Override public Observable[] call(ObservableList<String> param) { return new Observable[]{param}; } }; Predicate<ObservableList<String>> nonEmptyFilter = new Predicate<ObservableList<String>>() { @Override public boolean test(ObservableList<String> obsl) { boolean nonEmpty = ! obsl.isEmpty(); for (String item : obsl) { nonEmpty = nonEmpty && (null != item) && ("" != item); }; return nonEmpty; } }; ObservableList<ObservableList<String>> basicSimple = FXCollections.observableArrayList(); ObservableList<ObservableList<String>> basicComposed = FXCollections.observableArrayList( identityExtractor ); ObservableList<ObservableList<String>> filteredSimple = basicSimple.filtered( nonEmptyFilter ); ObservableList<ObservableList<String>> filteredComposed = basicComposed.filtered( nonEmptyFilter ); System.out.println("Basic testing"); System.out.println("Add invalid"); basicSimple.addAll( FXCollections.observableArrayList("") ); System.out.println( basicSimple ); System.out.println( filteredSimple ); System.out.println("Make it valid"); basicSimple.get(0).addAll("first"); System.out.println( filteredSimple ); System.out.println("Add valid"); basicSimple.addAll( FXCollections.observableArrayList("Second") ); System.out.println( filteredSimple ); System.out.println("Composed testing"); System.out.println("Add invalid"); basicComposed.addAll( FXCollections.observableArrayList("") ); System.out.println( basicComposed ); System.out.println( filteredComposed ); System.out.println("Make it valid"); basicComposed.get(0).addAll("first"); System.out.println( filteredComposed ); System.out.println("Add valid"); basicComposed.addAll( FXCollections.observableArrayList("Second") ); System.out.println( filteredComposed );
I found a strange error during testing:
[info] Running helloworld.HelloWorld Basic testing Add invalid [[]] [] Make it valid [] Add valid [[Second]] Composed testing Add invalid [[]] [] Make it valid [error] (JavaFX Application Thread) java.lang.ArrayIndexOutOfBoundsException java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at javafx.collections.transformation.FilteredList.updateFilter(FilteredList.java:298) at javafx.collections.transformation.FilteredList.update(FilteredList.java:239) at javafx.collections.transformation.FilteredList.sourceChanged(FilteredList.java:137) at javafx.collections.transformation.TransformationList.lambda$getListener$16(TransformationList.java:106) at javafx.collections.transformation.TransformationList$$Lambda$63/1596532574.onChanged(Unknown Source) at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88) at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164) at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73) at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233) at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:485) at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541) at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205) at com.sun.javafx.collections.ObservableListWrapper.access$200(ObservableListWrapper.java:45) at com.sun.javafx.collections.ObservableListWrapper$1$1.invalidated(ObservableListWrapper.java:75) at com.sun.javafx.collections.ListListenerHelper$SingleInvalidation.fireValueChangedEvent(ListListenerHelper.java:126) at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73) at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233) at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482) at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541) at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205) at javafx.collections.ModifiableObservableListBase.addAll(ModifiableObservableListBase.java:102) at javafx.collections.ObservableListBase.addAll(ObservableListBase.java:245) at helloworld.HelloWorld.start(HelloWorld.java:87) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(LauncherImpl.java:821) at com.sun.javafx.application.LauncherImpl$$Lambda$55/7143454.run(Unknown Source) at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(PlatformImpl.java:323) at com.sun.javafx.application.PlatformImpl$$Lambda$51/397137382.run(Unknown Source) at com.sun.javafx.application.PlatformImpl.lambda$null$164(PlatformImpl.java:292) at com.sun.javafx.application.PlatformImpl$$Lambda$53/1802784360.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(PlatformImpl.java:291) at com.sun.javafx.application.PlatformImpl$$Lambda$52/1184782272.run(Unknown Source) at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication.lambda$null$45(GtkApplication.java:126) at com.sun.glass.ui.gtk.GtkApplication$$Lambda$43/450111611.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) [trace] Stack trace suppressed: run last compile:run for the full output. [] Add valid [[Second]]
The difference between basicSimple and basicComposed is that the latter has a qualifier, so it receives update events. In the middle of processing the update event, an exception was thrown by native code. What should I consider for a sample code to work without errors?
Debug bit
I inserted println at the end of the nonEmptyFilter predicate nonEmptyFilter . It works correctly, and the ObservableList is passed to it, as expected, a new value that was just updated. The error occurs later when some iterative FilteredList code is executed.
source share