I'm trying to write a custom TableViewSelectionModel
to use with my TableView
in JavaFX. I've implemented all the abstract methods, and am updating the selected items and selected cells lists. However, the actual selection being shown in the table does not change when I click on another row.
Here is a simplified example, which shows this behavior:
import java.util.*;
import javafx.scene.control.*;
import javafx.scene.control.TableView.TableViewSelectionModel;
import javafx.collections.*;
import javafx.beans.property.ReadOnlyListWrapper;
public class MySelectionModel<S> extends TableViewSelectionModel<S>{
Set<Integer> selection = new HashSet<>();
final ObservableList<TablePosition<S, ?>> selectedCells = FXCollections.<TablePosition<S, ?>>observableArrayList();
final ObservableList<S> selectedItems = FXCollections.<S>observableArrayList();
final ObservableList<Integer> selectedIndices = FXCollections.<Integer>observableArrayList();
public MySelectionModel(TableView<S> tableview){
super(tableview);
setCellSelectionEnabled(false);
}
public ObservableList<S> getSelectedItems(){
return new ReadOnlyListWrapper<S>(selectedItems);
}
public void clearSelection(int row, TableColumn<S, ?> tableColumn){
selection.remove(Integer.valueOf(row));
updateSelection();
}
public void clearAndSelect(int row, TableColumn<S, ?> tableColumn){
selection = Collections.singleton(row);
updateSelection();
}
public void select(int row, TableColumn<S, ?> tableColumn){
selection.add(Integer.valueOf(row));
updateSelection();
}
public boolean isSelected(int row, TableColumn<S, ?> tableColumn){
return selection.contains(Integer.valueOf(row));
}
public ObservableList<TablePosition> getSelectedCells(){
return new ReadOnlyListWrapper<TablePosition>((ObservableList<TablePosition>)(Object)selectedCells);
}
public ObservableList<Integer> getSelectedIndices(){
return new ReadOnlyListWrapper<Integer>(selectedIndices);
}
public void selectBelowCell(){}
public void selectAboveCell(){}
public void selectRightCell(){}
public void selectLeftCell(){}
public void updateSelection(){
List<TablePosition<S, ?>> positions = new ArrayList<>();
List<S> items = new ArrayList<>();
List<Integer> indices = new ArrayList<>();
TableView<S> tableView = getTableView();
for(Integer i : selection){
positions.add(new TablePosition<S, Object>(tableView, i.intValue(), null));
items.add(getTableView().getItems().get(i.intValue()));
indices.add(i);
}
selectedCells.setAll(positions);
selectedItems.setAll(items);
selectedIndices.setAll(indices);
}
}
Which is being set on the TableView
like this:
TableView<ObservableList<MyData>> table = new TableView<>();
table.setSelectionModel(new MySelectionModel(table));
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
I've confirmed that the new indices are being correctly set by adding ListChangeListener
s on the two backing ObservableList
s and displaying the Change
s. The output is what I'd expect, e.g.
Selected Cells { [TablePosition [ row: 8, column: null, tableView: TableView@11924c25[styleClass=table-view] ]] replaced by [TablePosition [ row: 12, column: null, tableView: TableView@11924c25[styleClass=table-view] ]] at 0 }
Selected Items { [[MyCustomTableView$Cell@1c988ebb, MyCustomTableView$Cell@6b80b2be]] replaced by [[MyCustomTableView$Cell@4a17d76d, MyCustomTableView$Cell@6e48d6d]] at 0 }
Is there anything I'm missing that would is needed for the TableView
to update its selection when the TableViewSelectionModel
changes its selection?