【问题标题】:Custom TableViewSelectionModel not updating自定义 TableViewSelectionModel 未更新
【发布时间】:2015-11-15 04:13:42
【问题描述】:

我正在尝试编写一个自定义 TableViewSelectionModel 以在 JavaFX 中与我的 TableView 一起使用。我已经实现了所有的抽象方法,并且正在更新选定的项目和选定的单元格列表。但是,当我单击另一行时,表格中显示的实际选择不会改变。

这是一个简化的示例,它显示了这种行为:

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);

我已通过在两个支持ObservableLists 上添加ListChangeListeners 并显示Changes 来确认新索引设置正确。输出是我所期望的,例如

选定单元格 { [TablePosition [ row: 8, column: null, tableView: TableView@11924c25[styleClass=table-view] ]] 替换为 [TablePosition [ row: 12, column: null, tableView: TableView@11924c25[ styleClass=table-view] ]] at 0 }

选定项目 { [[MyCustomTableView$Cell@1c988ebb, MyCustomTableView$Cell@6b80b2be]] 替换为 [[MyCustomTableView$Cell@4a17d76d, MyCustomTableView$Cell@6e48d6d]] 在 0 }

TableViewSelectionModel 更改其选择时,TableView 是否需要更新其选择?

【问题讨论】:

  • 您是在实施getSelectedIndices(),还是在选择更改时修改该列表?
  • @James_D 我没去过,但我已经添加了它,它仍然显示同样的问题。
  • 可能需要minimal reproducible example。 (我知道使用TableViewSelectionModel 实现很难做到最小化。)
  • @James_D 我希望这不是必需的。保持简短的方法太多:P 我已经添加了我能做到的最短的可复制版本。

标签: java javafx selectionmodel


【解决方案1】:

除了您已经拥有的方法之外,您似乎需要覆盖的方法是

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(...) 返回一个不可修改的列表,因此如果您选择单行,然后尝试将项目添加到选择中,您会得到一个UnsupportedOperationException。您的clearAndSelect 需要实现为

public void clearAndSelect(int row, TableColumn<S, ?> tableColumn){
    selection.clear();
    selection.add(row);
    updateSelection();
}

【讨论】:

  • 不知何故,这适用于我在此处发布的示例,但不适用于我的实际代码:P。但是现在我有一个工作示例应该很容易修复。感谢您的解决方案。
猜你喜欢
  • 2018-01-29
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
  • 2014-09-13
  • 2015-01-15
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多