JavaFX: How to bind multiple properties in a list?

Related searches

I have a class SimpleElement which has a weight field and the second one has a list of SimpleElement and a weight field which depends on the sum of weight of all other SimpleElements containing in the list. Any one has any idea how to do that by binding?

My code:

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;

public class SimpleElement {

    IntegerProperty weight;

    public SimpleElement() {
        weight = new SimpleIntegerProperty();
    }

    public int getWeight() {
        return weight.get();
    }

    public void setWeight(int weight) {
        this.weight.set(weight);
    }

    public IntegerProperty weightProperty() {
        return weight;
    }
}

and

import java.util.ArrayList;
import java.util.List;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;

public class RootElement {

    List<SimpleElement> elements;
    IntegerProperty weight;

    public RootElement() {
        elements = new ArrayList<>();
        weight = new SimpleIntegerProperty();
    }

    public void addelements(SimpleElement element) {
        elements.add(element);
    }
}

The RootElement class can be rewritten to create a binding to each SimpleElement, adding them up:

public class RootElement {
    List<SimpleElement> elements;
    IntegerProperty weight;
    NumberBinding binding;

    public RootElement() {
        elements = new ArrayList<>();
        weight = new SimpleIntegerProperty();
    }

    public void addelements(SimpleElement element) {
        elements.add(element);

        if (binding == null) {
            binding = element.weightProperty().add(0);
        } else {
            binding = binding.add(element.weightProperty());
        }

        weight.bind(binding);
    }

    public Integer getWeight() {
        return weight.get();
    }

    public ReadOnlyIntegerProperty weightProperty() {
        return weight;
    }
}

Example of usage:

public static void main(String[] args) {
    SimpleElement se1 = new SimpleElement();
    SimpleElement se2 = new SimpleElement();
    SimpleElement se3 = new SimpleElement();
    RootElement root = new RootElement();

    root.addelements(se1);
    root.addelements(se2);
    root.addelements(se3);

    root.weightProperty().addListener(new ChangeListener<Number>() {
        @Override
        public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
            System.out.println(newValue);
        }
    });

    se1.setWeight(3);
    se2.setWeight(2);
    se1.setWeight(4);
}

The execution of the code above produces:

3

5

6

JavaFX: How to bind multiple properties in a list?, The RootElement class can be rewritten to create a binding to each SimpleElement , adding them up: public class RootElement { List<SimpleElement > elements� JavaFX property binding allows you to synchronize the value of two properties so that whenever one of the properties changes, the value of the other property is updated automatically. Two types of binding are supported: Unidirectional binding: With unidirectional binding, the binding works in just one direction. For example, if you bind property A to […]


Crferreira's answer uses Fluent API to construct the chain of bindings, I find it hard to clean and maintain when objects can be removed or replaced. It's better to use Low-Level API.

Though a huge set of prebuilt binding stuff in JavaFX API, ListBinding will not be invalidated when one of its elements gets a new property value. So you have to create your IntegerBinding subclass, that listens to changes in list and rebinds to new properties itself.

Based on code from a similar answer.

import java.util.ArrayList;
import java.util.List;
import javafx.beans.binding.IntegerBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;

class RootElement {

    ObservableList<SimpleElement> elements = FXCollections.observableList(new ArrayList<SimpleElement>());

    IntegerBinding totalWeight;

    public RootElement() {

        totalWeight = new SumOfWeightsForListOfSimpleElementsIntegerBinding(elements);

    }

    public void addElement(SimpleElement element) {

        elements.add(element);

    }

    public void removeElement(SimpleElement element) {

        elements.remove(element);

    }

    public Integer getWeigth() {
        return totalWeight.getValue();
    }

}

class SimpleElement {

    IntegerProperty weight;

    public SimpleElement() {
        this(0);
    }

    public SimpleElement(Integer weight) {
        this.weight = new SimpleIntegerProperty(weight);
    }

    public int getWeight() {
        return weight.get();
    }

    public void setWeight(int weight) {
        this.weight.set(weight);
    }

    public IntegerProperty weightProperty() {
        return weight;
    }

}

class SumOfWeightsForListOfSimpleElementsIntegerBinding extends IntegerBinding {

    // Reference to our observable list 
    private final ObservableList<SimpleElement> boundList;

    // Array of currently observed properties of elements of our list
    private IntegerProperty[] observedProperties = {};

    // Listener that has to call rebinding in response of any change in observable list
    private final ListChangeListener<SimpleElement> BOUND_LIST_CHANGE_LISTENER
            = (ListChangeListener.Change<? extends SimpleElement> change) -> {
                refreshBinding();
            };

    SumOfWeightsForListOfSimpleElementsIntegerBinding(ObservableList<SimpleElement> boundList) {
        this.boundList = boundList;
        boundList.addListener(BOUND_LIST_CHANGE_LISTENER);
        refreshBinding();
    }

    @Override
    protected int computeValue() {
        int i = 0;
        for (IntegerProperty bp : observedProperties) {
            i += bp.get();
        }

        return i;
    }

    @Override
    public void dispose() {
        boundList.removeListener(BOUND_LIST_CHANGE_LISTENER);
        unbind(observedProperties);
    }

    private void refreshBinding() {
        // Clean old properties from IntegerBinding's inner listener
        unbind(observedProperties);

        // Load new properties    
        List<IntegerProperty> tmplist = new ArrayList<>();
        boundList.stream().map((boundList1) -> boundList1.weightProperty()).forEach((integerProperty) -> {
            tmplist.add(integerProperty);
        });

        observedProperties = tmplist.toArray(new IntegerProperty[0]);

        // Bind IntegerBinding's inner listener to all new properties
        super.bind(observedProperties);

        // Invalidate binding to generate events
        // Eager/Lazy recalc depends on type of listeners attached to this instance
        // see IntegerBinding sources
        this.invalidate();
    }
}

public class Main {

    public static void main(String[] args) {
        SimpleElement se1 = new SimpleElement(10);
        SimpleElement se2 = new SimpleElement(20);
        SimpleElement se3 = new SimpleElement(30);
        RootElement root = new RootElement();

        root.totalWeight.addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
            System.out.println(newValue);
        });

        root.addElement(se1);
        root.addElement(se2);
        root.addElement(se3);

        se1.setWeight(1000);
        root.removeElement(se3);

    }

}

It's sad that such a common task as monitoring a sum of element's properties in a list requires that ugly boilerplate.

Using JavaFX Properties and Binding, Bindings are assembled from one or more sources, known as dependencies. A binding observes its list of dependencies for changes, and then updates itself� 1 Using JavaFX Properties and Binding. In this tutorial you learn how to use properties and binding in JavaFX applications. The tutorial describes relevant APIs and provides working examples that you can compile and run.


simply get the sum and bind the property to the sum. Therefore, any changes made to the sum will be observed by the binding property

[SOLVED] JavaFX bind to multiple properties, This is possible by binding to a boolean expression via Bindings : button. disableProperty().bind( Bindings.and( textField.textProperty(). Using JavaFX Properties and Binding. In this tutorial you learn how to use properties and binding in JavaFX 2 applications. The tutorial describes relevant APIs and provides working examples that you can compile and run.


Creating aggregate JavaFX bindings – Andres Almiray, The standard JavaFX API provides a class named Bindings that can be used to ObservableValue, Binding, Expression, and/or Property into another calculate an aggregate binding based on a list of observable values. Adding and modifying a List of Strings in a JavaFx ListView is a relatively easy task, although may not be completely intuitive at first glance. In order to have changes to a List automatically reflected in a ListView you will need to make use of the ListProperty class, however setting items in the property is not…


JavaFX: Binding Properties, JavaFX property binding allows you to synchronize the value of two properties so that whenever Every property has a bind and a bindBiDirectional method. So it is possible to add unidirectional binding to a property with bidirectional binding and vice-versa. However, this practice is discouraged. It is possible to have multiple bidirectional bindings of one Property. JavaFX bidirectional binding implementation use weak listeners.


11 List View. In this chapter, you learn how to create lists in your JavaFX applications. The ListView class represents a scrollable list of items.Figure 11-1 shows the list of available accommodation types in a hotel reservation system.