Hay {{X0} } que se utiliza para detectar cambios dentro de los elementos de ObservableList creados a través de ObservableList.observableArrayList(Callback<E,Observable[]> extractor).

¿Cómo recupero los elementos exactos que provocaron que se activara el cambio?

Editar

Quizás la pregunta no sea lo suficientemente clara, daré un ejemplo.

class Foo {
    private StringProperty name = new SimpleStringProperty();
    public final StringProperty nameProperty() { return name; }
    public final String getName() { return name.get(); }
    public final void setName(String n) { name.set(n); }
    public Foo(String fooName) { setName(fooName); }
}

// Creates an ObservableList with an extractor
ObservableList<Foo> fooList = FXCollections.observableArrayList(foo -> new Observable[] { foo.nameProperty() });
Foo fooA = new Foo("Hello");
Foo fooB = new Foo("Kitty");
fooList.add(fooA);
fooList.add(fooB);

fooList.addListener(new ListChangeListener<Foo>() {
     public void onChanged(Change<Foo> c) {
         while (c.next()) {
            if (c.wasUpdated()) {
                // One or more of the elements in list has/have an internal change, but I have no idea which element(s)!
            }
        }
    }
});

fooB.setName("Mickey");

fooB.setName() activará un cambio en ListChangeListener, que la condición wasUpdated() devolvería true. Sin embargo, no tengo forma de saber que es fooB lo que ha cambiado dentro del oyente.

Esto puede parecer trivial, pero tengo una aplicación de mapas donde la lista almacena las cosas que el mapa tiene que representar. Cuando uno de los elementos cambia su posición (es decir, lat / long), necesito volver a trazar en el mapa. Si no tengo idea de qué elemento ha cambiado de ubicación, tendré que volver a dibujar todo lo que ya tengo.

3
Jai 15 nov. 2017 a las 09:43

2 respuestas

La mejor respuesta

Puede obtener los índices de los elementos que se cambiaron, lo que le brinda información útil:

import javafx.beans.Observable;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;

public class ListUpdateTest {

    public static void main(String[] args) {

        ObservableList<Foo> fooList = FXCollections.observableArrayList(foo -> new Observable[] { foo.nameProperty() });
        Foo fooA = new Foo("Hello");
        Foo fooB = new Foo("Kitty");
        fooList.add(fooA);
        fooList.add(fooB);

        fooList.addListener((Change<? extends Foo> c) -> {
             while (c.next()) {
                if (c.wasUpdated()) {
                    int start = c.getFrom() ;
                    int end = c.getTo() ;
                    for (int i = start ; i < end ; i++) {
                        System.out.println("Element at position "+i+" was updated to: " +c.getList().get(i).getName() );
                    }
                }
            }
        });

        fooB.setName("Mickey");
    }

    public static class Foo {
        private StringProperty name = new SimpleStringProperty();
        public final StringProperty nameProperty() { return name; }
        public final String getName() { return name.get(); }
        public final void setName(String n) { name.set(n); }
        public Foo(String fooName) { setName(fooName); }
    }
}

Tenga en cuenta que no puede determinar a partir del evento de cambio de lista las propiedades reales que cambiaron en esos elementos de lista (por lo tanto, si su extractor señaló dos o más propiedades, no hay forma de encontrar cuál de esas propiedades cambió), y no forma de obtener el valor anterior. Sin embargo, esto puede ser suficiente para su caso de uso.

5
James_D 15 nov. 2017 a las 14:41

Directamente de los documentos.

El uso típico es observar cambios en una ObservableList para enganchar o desenganchar (o agregar o eliminar un oyente) o para mantener alguna invariante en cada elemento de esa ObservableList. Un patrón de código común para hacer esto se parece a lo siguiente:

 ObservableList theList = ...;

 theList.addListener(new ListChangeListener<Item>() {
     public void onChanged(Change<tem> c) {
         while (c.next()) {
             if (c.wasPermutated()) {
                     for (int i = c.getFrom(); i < c.getTo(); ++i) {
                          //permutate
                     }
                 } else if (c.wasUpdated()) {
                          //update item
                 } else {
                     for (Item remitem : c.getRemoved()) {
                         remitem.remove(Outer.this);
                     }
                     for (Item additem : c.getAddedSubList()) {
                         additem.add(Outer.this);
                     }
                 }
             }
         }
     });

 }
1
Sedrick 15 nov. 2017 a las 07:00