Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8094778

FilteredList doesn't always handle update Changes from source list

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P4
    • 8u60
    • 8u25
    • javafx
    • Windows 7 SP1
      java version "1.8.0_25"
      Java(TM) SE Runtime Environment (build 1.8.0_25-b18)
      Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

    Description

      In the code below, at the end of the main method, the source ObservableList becomes not empty, and the FilteredList remains empty (because its Predicate returns false for all items in the list). When Foo zero's shown property is set to true, source fires an update change, but filtered doesn't add zero to itself. (Filtered doesn't fire an add change and it doesn't show Foo zero in toString.)

      If Foo one (which has shown set to true) is added to the source list along with Foo zero, zero gets added to filtered when its shown property is set to true.

      ----------
      import javafx.beans.Observable;
      import javafx.beans.property.BooleanProperty;
      import javafx.beans.property.ReadOnlyStringProperty;
      import javafx.beans.property.ReadOnlyStringWrapper;
      import javafx.beans.property.SimpleBooleanProperty;
      import javafx.collections.FXCollections;
      import javafx.collections.ListChangeListener;
      import javafx.collections.ObservableList;
      import javafx.collections.transformation.FilteredList;

      public class FilteredListBug {
          public static void main (String[] args) {
              ObservableList<Foo> source = FXCollections.observableArrayList(Foo::extractor);
              FilteredList<Foo> filtered = new FilteredList<>(source, Foo::isShown);
              
              source.addListener((ListChangeListener.Change<? extends Foo> change) -> {
                  while (change.next()) {
                      if (change.wasUpdated()) {
                          System.out.println("Source change: " + change.toString());
                      }
                      else if (change.wasAdded()) {
                          System.out.println("Source added: " + change.toString());
                      }
                  }
              });
              filtered.addListener((ListChangeListener.Change<? extends Foo> change) -> {
                  while (change.next()) {
                      if (change.wasUpdated()) {
                          System.out.println("Filtered change: " + change.toString());
                      }
                      else if (change.wasAdded()) {
                          System.out.println("Filtered added: " + change.toString());
                      }
                  }
              });
              
              System.out.println("Source: " + source);
              System.out.println("Filtered: " + filtered);
              System.out.println();
              
              Foo zero = new Foo("zero", false);
              Foo one = new Foo("one", true);
              //FilteredList works when Foos zero and one are added to the list.
              //It doesn't work when only Foo zero is added to the list.
              source.addAll(zero);
              System.out.println();
              zero.setShown(true);
              
              System.out.println();
              System.out.println("Source: " + source);
              System.out.println("Filtered: " + filtered);
          }
          
          public static class Foo {
              public static Observable[] extractor (Foo release) {
                  return new Observable[] { release.shown };
              }
              
              private final ReadOnlyStringWrapper id;
              private final BooleanProperty shown;
              
              public Foo (String id, boolean shown) {
                  this.id = new ReadOnlyStringWrapper(this, "id", id);
                  this.shown = new SimpleBooleanProperty(this, "shown", shown);
              }
              
              public String getId () { return id.get(); }
              public ReadOnlyStringProperty idProperty () { return id.getReadOnlyProperty(); }
              
              public boolean isShown () { return shown.get(); }
              public void setShown (boolean value) { shown.set(value); }
              public BooleanProperty shownProperty () { return shown; }
              
              @Override
              public String toString () {
                  return "Foo(" + getId() + ", " + isShown() + ")";
              }
          }
      }
      ----------

      Attachments

        Issue Links

          Activity

            People

              vadim Vadim Pakhnushev
              duke J. Duke
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:
                Imported: