自定义 TableViewSelectionModel 未更新
Custom TableViewSelectionModel not updating
我正在尝试用 JavaFX 编写自定义 TableViewSelectionModel
to use with my TableView
。我已经实现了所有的抽象方法,并且正在更新选定的项目和选定的单元格列表。但是,当我单击另一行时,table 中显示的实际选择并没有改变。
这是一个简化的示例,显示了此行为:
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);
}
}
在 TableView
上设置如下:
TableView<ObservableList<MyData>> table = new TableView<>();
table.setSelectionModel(new MySelectionModel(table));
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
我已确认通过在两个支持 ObservableList
上添加 ListChangeListener
并显示 Change
来正确设置新索引。输出是我所期望的,例如
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 }
当 TableViewSelectionModel
更改其选择时,TableView
是否需要更新其选择的任何内容?
除了您已有的方法之外,您似乎需要重写的方法是
public void select(int row) ;
您可以通过委托给现有的 select
方法轻松实现:
@Override
public void select(int row) {
select(row, null);
}
我还建议覆盖以下内容:
@Override
public void clearAndSelect(int row) {
clearAndSelect(row, null);
}
@Override
public void selectRange(int start, int end) {
IntStream.range(start, end).forEach(selection::add);
updateSelection();
}
@Override
public boolean isSelected(int row) {
return isSelected(row, null);
}
另请注意,您有一个错误。 Collections.singleton(...)
returns 一个不可修改的列表,因此如果您 select 一行,然后尝试将项目添加到 selection,您会得到一个 UnsupportedOperationException
。您的 clearAndSelect
需要实施为
public void clearAndSelect(int row, TableColumn<S, ?> tableColumn){
selection.clear();
selection.add(row);
updateSelection();
}
我正在尝试用 JavaFX 编写自定义 TableViewSelectionModel
to use with my TableView
。我已经实现了所有的抽象方法,并且正在更新选定的项目和选定的单元格列表。但是,当我单击另一行时,table 中显示的实际选择并没有改变。
这是一个简化的示例,显示了此行为:
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);
}
}
在 TableView
上设置如下:
TableView<ObservableList<MyData>> table = new TableView<>();
table.setSelectionModel(new MySelectionModel(table));
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
我已确认通过在两个支持 ObservableList
上添加 ListChangeListener
并显示 Change
来正确设置新索引。输出是我所期望的,例如
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 }
当 TableViewSelectionModel
更改其选择时,TableView
是否需要更新其选择的任何内容?
除了您已有的方法之外,您似乎需要重写的方法是
public void select(int row) ;
您可以通过委托给现有的 select
方法轻松实现:
@Override
public void select(int row) {
select(row, null);
}
我还建议覆盖以下内容:
@Override
public void clearAndSelect(int row) {
clearAndSelect(row, null);
}
@Override
public void selectRange(int start, int end) {
IntStream.range(start, end).forEach(selection::add);
updateSelection();
}
@Override
public boolean isSelected(int row) {
return isSelected(row, null);
}
另请注意,您有一个错误。 Collections.singleton(...)
returns 一个不可修改的列表,因此如果您 select 一行,然后尝试将项目添加到 selection,您会得到一个 UnsupportedOperationException
。您的 clearAndSelect
需要实施为
public void clearAndSelect(int row, TableColumn<S, ?> tableColumn){
selection.clear();
selection.add(row);
updateSelection();
}