Is it possible to make a property which listen to changes of custom objects in javafx?
Asked Answered
P

1

6

Let's assume I have an entity class Foo which contains some fields, getters, setters and constructor. For example:

public class Foo {
private Integer a = 0;
private Integer b = 0;

public Foo() {
}

public Integer getA() {
    return a;
}

public void setA(Integer a) {
    this.a = a;
}

public Integer getB() {
    return b;
}

public void setB(Integer b) {
    this.b = b;
}
}

Then i want to know when a or b changes. I know that there is an ObjectProperty in javaFX. So i'm creating Object Property:

ObjectProperty<Foo> fooProperty = new SimpleObjectProperty<>(new Foo());

Then in order to know about changes of a and b fields, I add ChangeListener:

fooProperty.addListener((observable, oldValue, newValue) -> {
    System.out.println("Property changed!");
});

Then experiments:

fooProperty.set(new Foo());

working well, but next line:

fooProperty.get().setA(10)

does not invoke listener. The reason for that is clear. Last line actually doesn't change the Foo object (reference remains the same).

I have some possible solutions. But all of them are not elegant enough. For example changing each field as a property and adding the same listener for each variable.

So, the question is. What is the way to add listener for changes of the fields of custom object?

Pathan answered 20/6, 2017 at 13:25 Comment(1)
Isn't this just solved by implementing a and b as IntegerPropertys and using a fixed Foo instance? Or am I misunderstanding the question?Gastrocnemius
F
5

do not know if this what you want or not, you may take it for reference.

First i create a class, its function is to carry information.

public class EventObj{
  private String message;
  private Object newObj;

  public EventObj(String msg, Object obj){
    this.message = msg;
    this.newObj = obj;
  }

  public String getMessage(){
    return this.message;
  }

  public Object getNewObj(){
    return this.newObj;
  }
}

then, create the Foo class, it has two Object fields, we are going to listen if they change.

public class Foo{
  private SimpleObjectProperty<Object> a;
  private SimpleObjectProperty<Object> b;

  private SimpleObjectProperty<EventObj> out;


  public Foo(){
    a = new SimpleObjectProperty<>();
    b = new SimpleObjectProperty<>();
    out = new SimpleObjectProperty<>();
    initEvent();
  }

  private void initEvent(){
    a.addListener(new ChangeListener<Object>(){
      @Override
      public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue){
        out.set(new EventObj("a changed", newValue));
      }
    });

    b.addListener(new ChangeListener<Object>(){
      @Override
      public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue){
        out.set(new EventObj("b changed", newValue));
      }
    });
  }

  public void setA(Object a){
    this.a.set(a);
  }

  public void setB(Object b){
    this.b.set(b);
  }

  public SimpleObjectProperty<EventObj> outProperty(){
    return out;
  }
}

in other class, using the code below, to listen if the a or b in foo has change.

Foo foo = new Foo();
foo.outProperty().addListener(new ChangeListener<EventObj>(){
  @Override
  public void changed(ObservableValue<? extends EventObj> observable, EventObj oldValue, EventObj newValue){
    System.out.println(newValue.getMessage() + ", new value is : " + newValue.getNewObj());
  }
});

foo.setA(new Object());
foo.setB(new Object());

in this case, we just use Object class, if you wanna use a custom class to replace, don't forget to override its hashCode() and equals() methods to determine whether the two objects are the same.

Fecundate answered 20/6, 2017 at 15:20 Comment(2)
Thanks, that's better than all possibilities i had.Pathan
@NazariiMediukh you're welcome, my pleasure to help you.Fecundate

© 2022 - 2024 — McMap. All rights reserved.