16

I really have difficulties to understand how the ObservableList object is working in JavaFX. I want to monitor if an object in the List has been modified. So far, I only see that I can monitor if the List, as an entity itself, has been modified... but not the objects within the List:

ObservableList<Stuff> myList = FXCollections.<Stuff>observableArrayList();
myList.add(someStuff);

myList.addListener((ListChangeListener.Change<? extends Stuff> change) -> {
    while(change.next()){
        if(change.wasUpdated()){
            System.out.println("Update detected");
        }
        else if(change.wasPermutated()){

        }
        else{
            for (Stuff remitem : change.getRemoved()) {
                //do things
            }
            for (Stuff additem : change.getAddedSubList()) {
                //do things
            }
        }
    }
});
someStuff.setThing("clobber"); // trigger listener

Is there a way to do this? I'm looking for a workflow such that a modification to the object triggers → modification on the list → refresh on a some view.

Thanks

Neuron
  • 5,141
  • 5
  • 38
  • 59
BlackLabrador
  • 2,829
  • 5
  • 18
  • 21
  • 2
    possible duplicate of [Java 8: Observable List - Invalidation Listener nor Change Listener is called in case of property change](http://stackoverflow.com/questions/26730034/java-8-observable-list-invalidation-listener-nor-change-listener-is-called-in) – James_D Nov 10 '14 at 12:10
  • 4
    See also this blog post: [Properties Extractor: Best way to get the ListView instantly updating its elements](http://www.jensd.de/wordpress/?p=1650) – Tomas Mikula Nov 10 '14 at 14:03

2 Answers2

6

If you want to monitor changes of the objects inside the list instead of the list itself, then you have to attach listeners to the objects of the list and not to the list.

Of course to be able to do this, the objects must support this. java.lang.Object does not support this.

Instead take a look at the ObservableValue interface. Objects that implement this interface support this kind of monitoring you're looking for. The javadoc page of ObservableValue lists all the JavaFX built-in classes that implement this interface (the list is quite looooong).

Either you have to use any of those, or you have to implement the interface yourself. And add your change listeners to the objects and not to the list.

icza
  • 389,944
  • 63
  • 907
  • 827
  • 10
    There is already API for doing this: see http://stackoverflow.com/questions/26730034/java-8-observable-list-invalidation-listener-nor-change-listener-is-called-in/26734379#26734379 – James_D Nov 10 '14 at 12:11
2
public static void main(String[] args) {
    ArrayList<Integer> intList = new ArrayList();
    intList.add(0);
    intList.add(1);

    ObservableList<Integer> ob = FXCollections.observableArrayList(intList);
    ob.addListener(new ListChangeListener<Integer>() {
        @Override
        public void onChanged(javafx.collections.ListChangeListener.Change<? extends Integer> c) {
            System.out.println("Changed on " + c);
            if(c.next()){
                System.out.println(c.getFrom());
            }

        }

    });

    ob.set(0, 1);
}

The event (c in my case) is the index that the change occurred on (when you do .getFrom()). Also if you print the event out you get a string that tells you exactly what happend. You mistakenly interpret it has a change being done on the list as a whole!

Lealo
  • 331
  • 1
  • 3
  • 11
  • I have some problems with this answer. Firstly, c is not an event, it is a `Change` (and that is a pretty good descriptive name, why not use it?). Secondly, a `Change` is **not** and index. It isn't one and it doesn't represent one. It does *occur on* an index. If you fix that I'll retract my downvote and remove my comment. Make sure to @ mention me in the comments – Neuron Apr 24 '18 at 05:38
  • does not answer the question at all: was about being notified when a property of a contained element is modified, not if the list is modified – kleopatra Apr 24 '18 at 07:30