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

ListChangeListener.Change.getList() reports incorrect list for default TableView selection model

XMLWordPrintable

    • generic
    • generic

      FULL PRODUCT VERSION :
      Java HotSpot(TM) 64-Bit Server VM (build 25.152-b16, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 10.0.15063]

      A DESCRIPTION OF THE PROBLEM :
      1. Populate TableView with multiple rows.
      2. Add listener to TableView.getSelectionModel().
      3. Select a row.
      4. Reset TableView content.
      5. Observe that TableView's selection model publishes an event indicating that all new rows are selected.

      This seems to be caused by itemsContentListener in TableView.java (line 2111):

              final ListChangeListener<S> itemsContentListener = c -> {
                  updateItemCount();

                  List<S> items1 = getTableModel();

                  while (c.next()) {
                      if (c.wasReplaced() || c.getAddedSize() == getItemCount()) {
                          this.selectedItemChange = c;
                          updateDefaultSelection();
                          this.selectedItemChange = null;
                          return;
                      }

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Launch app, select first row and then press button. Selection event erroneously returns full TableView list instead of selected item list.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Printed to system.out:

      New selection: [StringProperty [value: alpha]]
      New selection: []
      ACTUAL -
      Printed to system.out:

      New selection: [StringProperty [value: alpha]]
      New selection: [StringProperty [value: delta], StringProperty [value: echo], StringProperty [value: foxtrot]]

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package test;

      import javafx.application.Application;
      import javafx.beans.property.Property;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.collections.ListChangeListener;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;

      import java.io.IOException;
      import java.util.stream.Collectors;
      import java.util.stream.Stream;

      /**
       * Launch app, select first row and then press button. Selection event erroneously returns
       * full TableView list instead of selected item list.
       */
      public class TestApplication extends Application {
      public static void main(String[] pArgs) {launch(pArgs);}

      @Override public void start(Stage pStage) throws IOException {
      Thread.setDefaultUncaughtExceptionHandler(
      (pThread, pThrowable) -> pThrowable.printStackTrace()
      );

              final TableView<Property<String>> tableView = new TableView<>();
              final TableColumn<Property<String>,String> col = new TableColumn<>("Col");
              col.setCellValueFactory(TableColumn.CellDataFeatures::getValue);
              tableView.getColumns().add(col);
              tableView.getItems().addAll(
                  Stream.of("alpha", "bravo", "charlie").map(SimpleStringProperty::new).collect(
                      Collectors.toList()
                  )
              );

              tableView.getSelectionModel().getSelectedItems().addListener(
                  (ListChangeListener<Property<String>>) change -> System.out.println(
                      "New selection: " + change.getList()
                  )
              );

              final Button btn = new Button("update content");
              btn.setOnMouseClicked(
                  event -> tableView.getItems().setAll(
                      Stream.of("delta", "echo", "foxtrot").map(SimpleStringProperty::new).collect(
                          Collectors.toList()
                      )
                  )
              );

      pStage.setTitle("Test");
      pStage.setScene(new Scene(new VBox(tableView, btn), 400, 300));
      pStage.show();
      }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      In listeners, access TableView.getSelectionModel().getSelectedItems() instead of change.getList().

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: