0

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 ?

VANILKA
  • 634
  • 1
  • 13
  • 32
  • Can you clarify what you are doing here? The change listener you registered will be notified if you change the value of `member`, i.e. if you do something like `member.set(new Member())`. If you want to be notified when the individual properties of some `Member` instance change, you need to register a listener with the individual property. – James_D Apr 05 '17 at 14:50
  • The individual properties are the "subjects" in the language of the observer pattern, if that helps. – James_D Apr 05 '17 at 15:04

2 Answers2

2

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.

James_D
  • 201,275
  • 16
  • 291
  • 322
1

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
geh
  • 71
  • 11
  • that is also OK. THX. But I need have field as properties ( I use TableView to show this elements). Sow the response above isb better for my case. – VANILKA Apr 05 '17 at 17:32