Reputation: 684
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
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
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