SelectedItems are empty if multiple rows are selected using different columns

I have a TableView in SelectionMode.MULTIPLE . Using ListChangeListener , I can catch the selection of several rows (by pressing Shift ).

However, my solution only works if the items are selected in the same column OR in an area without columns. Gif for illustration with 4 examples:

  • OK: Select 3 items using Shift in the status column
  • OK: Select 4 items with Shift in the Idx column
  • OK: Select 4 items with Shift , starting from the status column to the area without columns.
  • Error: Trying to select 4 items using Shift , starting with the "Status" column and the "Data item" column.

Selection of multiple items in different columns

The problem is that the SelectedItems -list is apparently empty in the last example. I would really appreciate your help in solving this problem.

Here is my approach:

 ObservableList<DataRowModel> dataRows = FXCollections.observableArrayList(); dataRows.addAll(dataSetModel.getRows()); tableDataRow.setItems(dataRows); tableDataRowStateColumn.setCellValueFactory(f -> f.getValue().getState()); tableDataRow.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); tableDataRow.getSelectionModel().getSelectedItems() .addListener((ListChangeListener.Change<? extends DataRowModel> c) -> { while (c.next()) { c.getRemoved().stream().forEach(remitem -> remitem.setSelected(false)); c.getAddedSubList().stream().forEach(additem -> additem.setSelected(true)); System.out.println(c.getList()); //Empty [] when selected using different columns } }); 

Just for a better understanding of my code: setSelected(...) sets a BooleanProperty to my DataRowModel that is bound to a status column.

Out of context, the reason for using this selected property seems rather silly. However, there are various other code snippets with ChangeListeners that are bound to the selected property.

SSCCE is ready to work:

 import javafx.application.Application; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; 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.Group; import javafx.scene.Scene; import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.stage.Stage; public class TableViewSample extends Application { private TableView<DataRowModel> tableDataRow = new TableView<DataRowModel>(); private TableColumn<DataRowModel, String> tableDataRowNameColumn = new TableColumn<>("Data Item"); private TableColumn<DataRowModel, String> tableDataRowStateColumn = new TableColumn<>("State"); private final ObservableList<DataRowModel> dataRows = FXCollections.observableArrayList( new DataRowModel("Concinna", false), new DataRowModel("Concinna", false), new DataRowModel("Concinna", false), new DataRowModel("Concinna", false), new DataRowModel("Concinna", false) ); public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { Scene scene = new Scene(new Group()); stage.setTitle("Table View Sample"); stage.setWidth(500); stage.setHeight(500); tableDataRow.setItems(dataRows); tableDataRowNameColumn.setCellValueFactory(f -> f.getValue().getName()); tableDataRowStateColumn.setCellValueFactory(f -> f.getValue().getState()); tableDataRow.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); tableDataRow.getSelectionModel().getSelectedItems() .addListener((ListChangeListener.Change<? extends DataRowModel> c) -> { while (c.next()) { c.getRemoved().stream().forEach(remitem -> remitem.setSelected(false)); c.getAddedSubList().stream().forEach(additem -> additem.setSelected(true)); } }); tableDataRow.getColumns().addAll(tableDataRowNameColumn, tableDataRowStateColumn); ((Group) scene.getRoot()).getChildren().addAll(tableDataRow); stage.setScene(scene); stage.show(); } public static class DataRowModel { private StringProperty name = new SimpleStringProperty(this, "name", ""); private BooleanProperty selected = new SimpleBooleanProperty(this, "selected", true); private StringProperty state = new SimpleStringProperty(this, "state", ""); public DataRowModel(String name, boolean selected) { this.name.setValue(name); this.selected.setValue(selected); this.selected.addListener((observable, oldVal, newVal) -> { getState(); // Refresh State value }); } public StringProperty getName() { return name; } public BooleanProperty isSelected() { return selected; } public void setSelected(boolean selected) { if (this.selected.getValue() != selected) this.selected.setValue(selected); } public StringProperty getState() { String stateStr = ""; if (selected.getValue()) stateStr += "Selected"; state.setValue(stateStr); return state; } } } 
+7
java java-8 javafx javafx-8
source share
1 answer

I managed to generate this by editing the example Person Person table.

This is a bug registered as https://bugs.openjdk.java.net/browse/JDK-8096787 and is fixed in version 8u60 , which is expected to be released in August 2015.

+2
source share

All Articles