I'm using LiveList
to bind the children of a group to a list containing the data of the children. here is an example:
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
ObservableList<Integer> intList = FXCollections.observableArrayList();
LiveList<Circle> circleList = LiveList.map(intList, i -> {
System.out.println("in");
return new Circle(i);
});
Group group = new Group();
Bindings.bindContent(group.getChildren(), circleList);
intList.add(2);
intList.clear();
}
public static void main(String[] args) {
launch(args);
}
}
My problem is that for each change in intList
the bound list is updated twice and which creates more objects than needed. Running the code gives:
in
in
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Children: duplicate children added: parent = Group@68887c42
at javafx.scene.Parent$2.onProposedChange(Parent.java:454)
at com.sun.javafx.collections.VetoableListDecorator$VetoableSubListDecorator.clear(VetoableListDecorator.java:529)
at com.sun.javafx.binding.ContentBinding$ListContentBinding.onChanged(ContentBinding.java:114)
at org.reactfx.collection.ChangeListenerWrapper.onChange(LiveList.java:439)
at org.reactfx.collection.ChangeListenerWrapper.onChange(LiveList.java:417)
at org.reactfx.util.ListNotifications.lambda$takeHead$0(NotificationAccumulator.java:317)
at org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:68)
at org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:57)
at org.reactfx.collection.MappedList.sourceChanged(MappedList.java:41)
at org.reactfx.collection.LiveList.lambda$observeQuasiChanges$7(LiveList.java:256)
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:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at com.sun.javafx.collections.ObservableListWrapper.clear(ObservableListWrapper.java:157)
at test1.Main.start(Main.java:27)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:748)
I want that for each element in intList
there will be a Circle
in the group's children. Why does this happen and how can I make it work properly?
The exception description is a red herring - the message "duplicate children added" is given whenever at the end of the change the number of children doesn't match what the change predicted it to be.
In your case, what actually happens is that the circle is not removed, so the
Group
ends up with a single child, yetclear
predicted it should have ended with 0.The reason why the circle is not removed is that it is not the same circle - your mapper creates a new
Circle
object whenever it is asked to perform the mapping, and so you get 1 circle when adding it, and a completely different one when clearing the list - this newCircle
cannot be removed from the children of the group, and so it remains with 1 child even after the call toclear
, triggering the exception.To solve this you would have to make sure you return the same target-object for the same source-object - this may not be possible if your list of integers may contain duplicates.