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

TableView TableViewArrayListSelectionModel getSelectedIndices() contains -1

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 9
    • 8u60
    • javafx
    • x86
    • windows_8

      FULL PRODUCT VERSION :
      java version "1.8.0_60"
      Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
      Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.3.9600]

      A DESCRIPTION OF THE PROBLEM :
      When a range selection is made in an table with a multiple selection model, getSelectedIndices may contain -1 values.
      First select a row for instance the third. then expand the selection to a row with an higher row nummer (f.e. the forth), then expand the selection to the first row.
      GetSelectedIndices contains now 0, -1, 2 instead of 0,1,2.

      REGRESSION. Last worked in version 8u51

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      create a table. set table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
      add a couple rows (5 or more)

      select the second row. (click on the second row)
      expand the selection to the third row (hold down shift-key click on the third row)
      expand the selection to the first row (hold down shift-key click on the first row)



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      the selected Indices ( table.getSelectionModel().getSelectedIndices()) should contain 0,1,2
      ACTUAL -
      the selected Indices contains 0,-1,2

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------


      import javafx.application.Application;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.collections.FXCollections;
      import javafx.collections.ListChangeListener.Change;
      import javafx.collections.ObservableList;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.control.ScrollPane;
      import javafx.scene.control.SelectionMode;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.control.cell.PropertyValueFactory;
      import javafx.scene.layout.Pane;
      import javafx.scene.layout.VBox;
      import javafx.scene.text.Font;
      import javafx.stage.Stage;

      public class FxTableSelectionTest extends Application {

         final ScrollPane sp = new ScrollPane();
         // @formatter:off
         private static final ObservableList<Person> data =
               FXCollections.observableArrayList(
                   
                   new Person("Astrid", "Gärtner"),
                   new Person("Holger", "Gärtner"),
                   new Person("Theo", "Gärtner"),
                   new Person("Klaus", "Gärtner"),
                   new Person("Sigrid", "Gärtner")
                   
               );

         // @formatter:on
         @Override
         public void start(Stage stage) {
            final Label label = new Label("Address Book");
            label.setFont(new Font("Arial", 20));
            Pane main = new VBox();
            TableView table = createTable();
            main.getChildren().addAll(label, table);
            Scene scene = new Scene(main);
            stage.setScene(scene);
            stage.setTitle("Test");

            stage.show();

         }
         @SuppressWarnings({ "rawtypes", "unchecked" })
         public static TableView createTable() {
            final TableView table = new TableView();
            table.setEditable(false);

            TableColumn firstNameCol = new TableColumn("First Name");
            firstNameCol.setCellValueFactory(new PropertyValueFactory<Object, Object>("firstName"));
            firstNameCol.setPrefWidth(200);
            TableColumn lastNameCol = new TableColumn("Last Name");
            lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));
            lastNameCol.setPrefWidth(200);
            table.setItems(data);
            table.getColumns().addAll(firstNameCol, lastNameCol);

            table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
            table.getSelectionModel().getSelectedIndices().addListener(FxTableSelectionTest::selectionChanged);
            return table;
         }

         private static void selectionChanged(Change<? extends Object> c) {
            while (c.next()) {
               System.out.println("Selection changed: " + c.getList());
            }
         }

         public static void main(String[] args) {
            launch(args);
            setUserAgentStylesheet(STYLESHEET_MODENA);
         }



         public static class Person {

            private final SimpleStringProperty firstName;
            private final SimpleStringProperty lastName;

            private Person(String fName, String lName) {
               this.firstName = new SimpleStringProperty(fName);
               this.lastName = new SimpleStringProperty(lName);
            }

            public String getFirstName() {
               return firstName.get();
            }

            public void setFirstName(String fName) {
               firstName.set(fName);
            }

            public String getLastName() {
               return lastName.get();
            }

            public void setLastName(String fName) {
               lastName.set(fName);
            }

         }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      use this to get the selected indices

         /**
          * gets the selected indices from the selected Cells, which are the selection model's
          * 'proper' internal data structure, selectedItems and selectedIndices are both 'read-only and unbacked'.
          * and due to a bug in jdk1.8.0_60 selectedIndices does not work properly in all cases
          * @return the list of indices of the selected rows
          */
         private List<Integer> getSelectedIndices() {
            Set<Integer> selectedRows = new HashSet<Integer>();
            List<TablePosition> selectedCells = m_FxTable.getSelectionModel().getSelectedCells();
            selectedCells.forEach(tablePosition -> {
               selectedRows.add(tablePosition.getRow());
            });
            return new ArrayList<>(selectedRows);
         }


            jgiles Jonathan Giles
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: