2015-11-15 6 views
1

Я пытаюсь написать пользовательский TableViewSelectionModel для использования с моим TableView в JavaFX. Я реализовал все абстрактные методы и обновляю выбранные элементы и списки выбранных ячеек. Однако фактический выбор, отображаемый в таблице, не изменяется, когда я нажимаю на другую строку.Пользовательский TableViewSelectionModel не обновляется

Вот упрощенный пример, который показывает такое поведение:

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

Я подтвердил, что новые индексы будучи правильно устанавливая путем добавления ListChangeListener s на две подложки ObservableList s и отображение Change s. Результат - то, что я ожидаю, например.

выбранных ячейки {[TablePosition [ряд: 8, колонок: нулевой, Tableview: TableView @ 11924c25 [styleClass = настольный вид]]] заменено [TablePosition [ряд: 12, колонок: нулевой, Tableview: TableView @ 11924c25 [styleClass = настольный вид]]] при 0}

Выбранные элементы {[[MyCustomTableView $ Cell @ 1c988ebb, MyCustomTableView $ Cell @ 6b80b2be]] заменяется на [[MyCustomTableView $ Cell @ 4a17d76d, MyCustomTableView $ Cell @ 6e48d6d]] at 0}

Есть ли что-то, что мне не хватает, что необходимо для TableView, чтобы обновить его выбор, когда TableViewSelectionModel меняет ваш выбор?

+0

Вы реализации 'getSelectedIndices()' или изменение этого списка при изменении выбора? –

+0

@James_D Я не был, но я добавил его, и он по-прежнему показывает ту же проблему. – resueman

+0

Вероятно, требуется [MCVE]. (Я знаю, что трудно быть минимальным с реализацией «TableViewSelectionModel».) –

ответ

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

Отсутствие e также у вас есть одна ошибка. Collections.singleton(...) возвращает неизменяемый список, поэтому, если вы выберете одну строку, попробуйте добавить элементы к выбору, вы получите UnsupportedOperationException. Ваши clearAndSelect должна быть реализована в виде

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

Как-то это работает для примера, который я разместил здесь, но не для моего фактического кода: P. Но теперь достаточно легко исправить, что у меня есть рабочий пример. Спасибо за решение. – resueman