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.

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());
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();
java java-8 javafx javafx-8
Luke
source share