I want to order a random number of Nodes according to their width. But I fail to calculate the sum of the width (using their properties), I have the following example code - I fail to get informed about the change of one of the properties:
@Override
public void start(Stage arg0) throws Exception {
List<SimpleIntegerProperty> l = IntStream.range(0, 10)
.mapToObj(SimpleIntegerProperty::new)
.collect(Collectors.toList());
ObservableList<IntegerProperty> widthAr = FXCollections.observableArrayList();
widthAr.addAll(l);
IntegerBinding nextheight = Bindings.createIntegerBinding(() -> widthAr.stream()
.mapToInt(IntegerProperty::get)
.sum(), widthAr);
nextheight.addListener((v, o, n) -> System.out.println("New value: " + v.getValue()));
//Now change randomly one of the IntegerProperties
ScheduledExecutorService tfsqueryScheduler = Executors.newScheduledThreadPool(1);
tfsqueryScheduler.scheduleAtFixedRate(() -> {
System.out.println("Changing");
int i = (int) Math.round(Math.random() * 9.4);
SimpleIntegerProperty v = l.get(i);
v.set(0);
}, 0, 3, TimeUnit.SECONDS);
System.out.println("Start...");
}
The nextheight.addListener is never called :( ... any ideas? Thanks!
By default, ObservableList
s only fire updates if the structure of the list changes (e.g. items are added to or removed from the list), not if the state of individual elements in the list changes. To create a list which fires notifications if properties belonging to any of its elements change, you need to create the list with an extractor.
In this case the property you are interested in is just the list element itself, so you need to replace
ObservableList<IntegerProperty> widthAr = FXCollections.observableArrayList();
with
ObservableList<IntegerProperty> widthAr =
FXCollections.observableArrayList(w -> new Observable[] {w});
Note also that, depending on your real use case, you may need to ensure your binding is not prematurely garbage collected, by making it a field instead of a local variable.