1

Say I have a JavaFX app with an observable class SomeObservableClass with some Properties:

public class SomeObservableClass{

  private StringProperty prop1 = new SimpleStringProperty();
  private DoubleProperty prop2 = new SimpleDoubleProperty();

  ... constructors, getters and setters
}

and another class which has a property:

public class ParentClass{
  private ObservableList<SomeObservableClass> sOC = FXCollections.observableArrayList();`
}

In this parent class I add a listener for the observable list: `

public class ParentClass{
  private ObservableList<SomeObservableClass> observableList = FXCollections.observableArrayList();

  public`ParentClass(List<SomeObservableClass> list){
    this.observableList.addAll(list);
    this.observableList.addListener((InvalidationListener) observable -> System.out.println("listener detected a change!"));`.
  }
}

Now say that in a controller class I change the property of one of the SomeObservableClass objects:

public class Controller(){
  private ParentClass parentClass;

  public void changeSomeProps(){
    SomeObservableClass anObservableObject = parentClass.getObservableList().get(0);
    anObservableObject.setProp1("newVal");
  }
}

This doesn't fire the listener. Why ?

I suspect I am lacking some code to make the listener aware that it should fire when any property of the list objects get modified, but I have no idea how to do that.

Gloomy
  • 1,091
  • 1
  • 9
  • 18
  • You shouldn't expect anything from your listner with this code because you modify the list "addAll" and then listen for event... So just swap addlistner and addall an you should see Something. Maybe you are modifying the list elsewhere but i can't see – user43968 May 01 '17 at 08:52
  • @user43968: No, what I mean by modifying the list is changing the properties of some of the ObservableList items. I'll edit to make it clearer. – Gloomy May 01 '17 at 08:55
  • When you modify prop1 or prop2 the list isn't changed. But why you doesn't register listner on prop1 and prop2 directly if it's what you want to listen ? – user43968 May 01 '17 at 09:01
  • @user43968 Because here I only put two for brevity, but in my case there's 15 or so properties - setting listeners for each and every one of them would be really unpractical. I just want to invalidate the object as soon as any of the properties gets changed. Also, how do I register listeners for each object of the list? should I iterate it? that feels really clumsy.... – Gloomy May 01 '17 at 09:26

1 Answers1

4

By default, ObservableList doesn't handle changes of item's contents. But instanciation of ObservableList with an extractor enables handling them.

ObservableList<SomeObservableClass> observableList = FXCollections.observableArrayList(
            e -> new Observable[]{e.prop1Property(), e.prop2Property()});

// add items and set listeners here

observableList.get(1).setProp1("newVal");
// It fires InvalidationListener and ListChangeListener.

EDIT:

It seems only ListChangeListener can identify updated items. Try it out please.

observableList.addListener((ListChangeListener) change -> {
    while (change.next()) {
        if (change.wasUpdated()) {
            SomeObservableClass changedItem = observableList.get(change.getFrom());
            System.out.println("ListChangeListener item: " + changedItem);
        }
    }
});
monolith52
  • 886
  • 2
  • 6
  • 9
  • Thanks a lot :-) Do you happen to know a good way to get *which* object was updated in the listener? – Gloomy May 05 '17 at 07:35