VANILKA
VANILKA

Reputation: 684

Notify . change of ObservableProperties

I have a class with following properties :

public class Member {
    private LongProperty version;

    private LongProperty id;

    private StringProperty name;

    private StringProperty surname;

    private StringProperty bornname;

    private StringProperty photo;

    private ObjectProperty<Age> age;

    private ObjectProperty<Sex> sex;
}

The problem is, when I add Change Listener on this object :

{
    private ObjectProperty<Member> member;

    public void addMemberChangeListener() {
        this.member.addListener((observable, oldValue, newValue) -> {
            if (newValue != null) {
                (...)
      }
    }
}

The change listener is not notified when I change value of properties. There is other way to notify listener about changes properties that implement standard Observer pattern ?

Upvotes: 0

Views: 947

Answers (2)

James_D
James_D

Reputation: 209339

If you want to add a single listener that is notified when any of the properties belonging to an instance of Member change, you can do something like the following:

Member member = new Member();

ChangeListener<Object> listener = (obs, oldValue, newValue) -> 
    System.out.println(obs + " changed from " + oldValue + " to " + newValue);

Stream.of(member.versionProperty(), member.idProperty(), member.nameProperty() /*, ... */)
    .forEach(p -> p.addListener(listener));

Note that the concrete property classes contain a constructor that takes an owning bean and a name of the property, so if you want to support this kind of use, you might want to use those constructors:

public class Member {

    private final LongProperty version = new SimpleLongProperty(this, "version");
    private final StringProperty name = new SimpleStringProperty(this, "name");

    // ...
}

and then you can leverage this in the change listener:

ChangeListener<Object> listener = (obs, oldValue, newValue) -> 
    System.out.println(((Property<?>)obs).getName() + " changed from " + oldValue + " to " + newValue);

Just a comment: in my experience, needing this is rare (at best). You will usually (always?) find it more convenient to register a different listener with each property, as typically the action to take when a property is changed depends on which property is changed. In other cases, there is usually a more elegant solution anyway.

Upvotes: 2

geh
geh

Reputation: 71

The properties listener is triggered when it changes value memberProperty.setValue(otherMember), not when you modify some property of its value memberProperty.getValue().setId(0)

Try to use PropertyChangeSupport.

Example:

public class Member
{

    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    private long id;
    private String name;

    public void addChangeListener(PropertyChangeListener listener)
    {
        this.pcs.addPropertyChangeListener(listener);
    }

    public void removeChangeListener(PropertyChangeListener listener)
    {
        this.pcs.removePropertyChangeListener(listener);
    }

    public void setId(long newId)
    {
        long oldId = this.id;
        this.id = newId;
        pcs.firePropertyChange("id", oldId, newId);
    }

    public void setName(String newName)
    {
        String oldName = this.name;
        this.name = newName;
        pcs.firePropertyChange("name", oldName, newName);
    }

}

Use:

Member member = new Member();

member.addChangeListener((evt) ->
{
    System.out.println("Changed "
            + evt.getPropertyName()
            + ": " + evt.getOldValue()
            + " -> " + evt.getNewValue());
});

member.setId(15);
member.setName("Maria");
member.setName("Ana");

Output:

Changed id: 0 -> 15
Changed name: null -> Maria
Changed name: Maria -> Ana

Upvotes: 1

Related Questions