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

TableView: selectedItems does not notify listeners if an element is removed

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P3 P3
    • tbd
    • jfx11, jfx20, jfx17, jfx19, jfx21
    • javafx
    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      Listeners on tableView.getSelectionModel().getSelectedItems() are not notified, when the selection changes because an element was removed.

      this works if the selectionMode is SINGLE, but not if it's MULTIPLE

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      run the sample application, select the first row "A" and press the "remove first" button.
      check console output.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Listeners on tableView.getSelectionModel().getSelectedItems() are notified
      ACTUAL -
      Listeners on tableView.getSelectionModel().getSelectedItems() are NOT notified

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

      import java.util.ArrayList;
      import java.util.List;

      import javafx.application.Application;
      import javafx.beans.InvalidationListener;
      import javafx.beans.property.ObjectProperty;
      import javafx.beans.property.SimpleObjectProperty;
      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.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.SelectionMode;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.HBox;
      import javafx.stage.Stage;

      public class TestTableSelectedItems extends Application {
      public static void main(String[] pArgs) {
      launch(pArgs);
      }

      @Override
      public void start(Stage pStage) {
      pStage.setTitle("TableView Test");

      final TableView<SomeItem> tableView = new TableView<>();
      tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

      ObservableList<SomeItem> list = FXCollections.observableArrayList();
      list.addAll(createItems());
      tableView.setItems(list.sorted());

      addColumns(tableView);

      BorderPane bp = new BorderPane(tableView);
      Button bRemove = new Button("remove first");
      bRemove.setOnAction(event -> {
      if (!list.isEmpty()) {
      list.remove(0);
      }
      });
      bp.setTop(new HBox(bRemove));

      pStage.setScene(new Scene(bp, 300, 500));
      pStage.show();

      tableView.getSelectionModel().selectedItemProperty().addListener((obs, o, n) -> {
      System.err.println("selected item: " + n);
      });

      tableView.getSelectionModel().getSelectedItems().addListener((InvalidationListener)o -> {
      System.err.println("invalidation listener - selected items: " + tableView.getSelectionModel().getSelectedItems());
      });
      tableView.getSelectionModel().getSelectedItems().addListener((ListChangeListener<SomeItem>) change -> {
      System.err.println("change listenener - selected items: " + tableView.getSelectionModel().getSelectedItems());
      });
      }

      private static void addColumns(final TableView<SomeItem> tableView) {
      TableColumn<SomeItem, String> colName = new TableColumn<>("Name");
      colName.setPrefWidth(200);
      colName.setCellValueFactory(item -> item.getValue().name);
      tableView.getColumns().add(colName);

      TableColumn<SomeItem, Integer> colNumber = new TableColumn<>("Number");
      colNumber.setPrefWidth(200);
      colNumber.setCellValueFactory(item -> item.getValue().number);
      tableView.getColumns().add(colNumber);
      }

      private static List<SomeItem> createItems() {
      List<SomeItem> items = new ArrayList<>();
      items.add(new SomeItem("A", 1));
      items.add(new SomeItem("B", 2));
      items.add(new SomeItem("C", 3));
      items.add(new SomeItem("D", 4));
      return items;
      }

      private static class SomeItem {
      private final StringProperty name = new SimpleStringProperty(this, "name");
      private final ObjectProperty<Integer> number = new SimpleObjectProperty<>(this, "number");

      public SomeItem(String name, int number) {
      this.name.set(name);
      this.number.set(number);
      }

      @Override
      public String toString() {
      return "SomeItem [name=" + name.get() + ", number=" + number.get() + "]";
      }
      }
      }
      ---------- END SOURCE ----------

      FREQUENCY : always


            angorya Andy Goryachev
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: