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

ListChangeListener on MultipleSelectionModel selectedItems does not always report correct item added.

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 8
    • Fix Version/s: 8
    • Component/s: javafx
    • Environment:

      jdk1.7.0_13-64

      Description

      The test code attached below produces following output:


      This ListView selection change listening does not look ok:
        select(a)
          list=[a]
          change from=0, to=1
          item added: a
        select(b) <--- selecting b, but getting 'item added: a' again
          list=[a, b]
          change from=0, to=1
          item added: a
        clearSelection()
          list=[]
          change from=0, to=0
          item removed: a
          item removed: b
        select(b) <--- select in different order
          list=[b]
          change from=0, to=1
          item added: b
        select(a) <--- here it is ok
          list=[a, b]
          change from=0, to=1
          item added: a




      import javafx.beans.property.SimpleStringProperty;
      import javafx.beans.property.StringProperty;
      import javafx.collections.FXCollections;
      import javafx.collections.ListChangeListener;
      import javafx.collections.ObservableList;
      import javafx.scene.control.ListView;
      import javafx.scene.control.SelectionMode;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.control.cell.PropertyValueFactory;

      public class Test {

        public static void main(String[] args) {
          Test test = new Test();
          test.listViewSelectedItemsProblem();
          test.regularObservableListWorksOk();
          test.tableViewSelectedItemsWorksOk();
        }

        public void listViewSelectedItemsProblem() {
          ObservableList<String> list = FXCollections.observableArrayList("a", "b", "c");

          final ListView<String> view = new ListView<String>(list);
          view.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

          view.getSelectionModel().getSelectedItems().addListener(new StringChangeListener());

          System.out.println("\nThis ListView selection change listening does not look ok:");
          System.out.println(" select(a)");
          view.getSelectionModel().select(0);

          System.out.println(" select(b) <--- selecting b, but getting 'item added: a' again");
          view.getSelectionModel().select(1);

          System.out.println(" clearSelection()");
          view.getSelectionModel().clearSelection();

          System.out.println(" select(b) <--- select in different order");
          view.getSelectionModel().select(1);

          System.out.println(" select(a) <--- here it is ok");
          view.getSelectionModel().select(0);
        }

        public void regularObservableListWorksOk() {
          ObservableList<String> list = FXCollections.observableArrayList("a", "b", "c");

          list.addListener(new StringChangeListener());

          System.out.println("\nChange listening in regular observable list works ok:");
          System.out.println(" Add d");
          list.add("d");
          System.out.println(" Add e");
          list.add("e");
          System.out.println(" Remove b");
          list.remove("b");
          System.out.println(" Remove a");
          list.remove("a");
        }

        public void tableViewSelectedItemsWorksOk() {
          final ObservableList<Item> data = FXCollections
              .observableArrayList(new Item("a"), new Item("b"), new Item("c"));

          TableColumn<Item, String> col = new TableColumn<Item, String>("Name");
          col.setCellValueFactory(new PropertyValueFactory<Item, String>("name"));
          TableView<Item> view = new TableView<Item>(data);
          view.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
          view.getSelectionModel().getSelectedItems().addListener(new ItemChangeListener());

          System.out.println("\nTableView selection change listening works ok:");
          System.out.println(" select(a)");
          view.getSelectionModel().select(0);

          System.out.println(" select(b) <-- this is where it went wrong for ListView");
          view.getSelectionModel().select(1);

          System.out.println(" clearSelection()");
          view.getSelectionModel().clearSelection();

          System.out.println(" select(b)");
          view.getSelectionModel().select(1);

          System.out.println(" select(a)");
          view.getSelectionModel().select(0);
        }

        private static class StringChangeListener implements ListChangeListener<String> {
          @Override
          public void onChanged(Change<? extends String> change) {
            System.out.println(" list=" + change.getList());
            while (change.next()) {
              System.out.println(" change from=" + change.getFrom() + ", to=" + change.getTo());
              if (change.wasPermutated()) {
                for (int i = change.getFrom(); i < change.getTo(); ++i) {
                  System.out.println(" wasPermutated index=" + i);
                }
              } else if (change.wasUpdated()) {
                System.out.println(" wasUpdated");
              } else {
                for (String item : change.getRemoved()) {
                  System.out.println(" item removed: " + item);
                }
                for (String item : change.getAddedSubList()) {
                  System.out.println(" item added: " + item);
                }
              }
            }
          }
        }

        private static class Item {
          private StringProperty name;

          private Item(String name) {
            this.name = new SimpleStringProperty(name);
          }

          public StringProperty nameProperty() {
            return name;
          }

          public String toString() {
            return name.getValue();
          }
        }

        private static class ItemChangeListener implements ListChangeListener<Item> {
          @Override
          public void onChanged(Change<? extends Item> change) {
            System.out.println(" selections=" + change.getList());
            while (change.next()) {
              System.out.println(" change from=" + change.getFrom() + ", to=" + change.getTo());
              for (Item item : change.getRemoved()) {
                System.out.println(" item removed: " + item);
              }
              for (Item item : change.getAddedSubList()) {
                System.out.println(" item added: " + item);
              }
            }
          }
        }
      }

        Attachments

          Activity

            People

            • Assignee:
              jgiles Jonathan Giles
              Reporter:
              duke J. Duke (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Due:
                Created:
                Updated:
                Resolved:
                Imported: