В этом случае вы должны использовать пользовательскую модель выбора, чтобы предотвратить выбор некоторых элементов.
Следующая реализация упрощена. Он не обрабатывает изменения списка элементов. Кроме того, он реализует только один выбор, но, надеюсь, он показывает общий подход:
public class CustomSelectionModel<T> extends MultipleSelectionModel<T> {
private final ListView<T> listView;
private final ObservableList<Integer> selectedIndices = FXCollections.observableArrayList();
private final ObservableList<Integer> selectedIndicesUnmodifiable = FXCollections.unmodifiableObservableList(selectedIndices);
private final ObservableList<T> selectedItems;
private BiPredicate<Integer, T> leavePredicate;
private BiPredicate<Integer, T> enterPredicate;
public BiPredicate<Integer, T> getLeavePredicate() {
return leavePredicate;
}
public void setLeavePredicate(BiPredicate<Integer, T> leavePredicate) {
this.leavePredicate = leavePredicate;
}
public BiPredicate<Integer, T> getEnterPredicate() {
return enterPredicate;
}
public void setEnterPredicate(BiPredicate<Integer, T> enterPredicate) {
this.enterPredicate = enterPredicate;
}
public CustomSelectionModel(ListView<T> listView) {
if (listView == null) {
throw new IllegalArgumentException();
}
this.listView = listView;
this.selectedItems = new TransformationList<T, Integer>(selectedIndices) {
@Override
protected void sourceChanged(ListChangeListener.Change<? extends Integer> c) {
beginChange();
while (c.next()) {
if (c.wasReplaced()) {
nextReplace(c.getFrom(), c.getTo(), c.getRemoved().stream().map(listView.getItems()::get).collect(Collectors.toList()));
} else if (c.wasRemoved()) {
nextRemove(c.getFrom(), c.getRemoved().stream().map(listView.getItems()::get).collect(Collectors.toList()));
} else if (c.wasAdded()) {
nextAdd(c.getFrom(), c.getTo());
}
}
endChange();
}
@Override
public int getSourceIndex(int index) {
return index;
}
@Override
public T get(int index) {
return listView.getItems().get(getSource().get(index));
}
@Override
public int size() {
return getSource().size();
}
};
}
@Override
public ObservableList<Integer> getSelectedIndices() {
return selectedIndicesUnmodifiable;
}
@Override
public ObservableList<T> getSelectedItems() {
return selectedItems;
}
@Override
public void selectIndices(int index, int... indices) {
clearAndSelect(index); // ignore all indices but the first
}
@Override
public void selectAll() {
selectFirst();
}
@Override
public void selectFirst() {
if (!listView.getItems().isEmpty()) {
clearAndSelect(0);
}
}
@Override
public void selectLast() {
if (!listView.getItems().isEmpty()) {
clearAndSelect(listView.getItems().size() - 1);
}
}
private void moveSelection(int oldIndex, int newIndex) {
if ((leavePredicate == null || leavePredicate.test(oldIndex, oldIndex == -1 ? null : listView.getItems().get(oldIndex)))
&& (enterPredicate == null || enterPredicate.test(newIndex, newIndex == -1 ? null : listView.getItems().get(newIndex)))) {
setSelectedIndex(newIndex);
if (newIndex == -1) {
selectedItems.clear();
setSelectedItem(null);
} else {
setSelectedItem(listView.getItems().get(newIndex));
if (isEmpty()) {
selectedIndices.add(newIndex);
} else {
selectedIndices.set(0, newIndex);
}
}
listView.getFocusModel().focus(newIndex);
}
}
@Override
public void clearAndSelect(int index) {
moveSelection(getSelectedIndex(), index);
}
@Override
public void select(int index) {
clearAndSelect(index);
}
@Override
public void select(T obj) {
int index = listView.getItems().indexOf(obj);
if (index >= 0) {
clearAndSelect(index);
}
}
@Override
public void clearSelection(int index) {
if (getSelectedIndex() == index) {
clearSelection();
}
}
@Override
public void clearSelection() {
moveSelection(getSelectedIndex(), -1);
}
@Override
public boolean isSelected(int index) {
return selectedIndices.contains(index);
}
@Override
public boolean isEmpty() {
return selectedIndices.isEmpty();
}
@Override
public void selectPrevious() {
int index = getSelectedIndex() - 1;
if (index >= 0) {
clearAndSelect(index);
}
}
@Override
public void selectNext() {
int index = getSelectedIndex() + 1;
if (index < listView.getItems().size()) {
clearAndSelect(index);
}
}
}
@Override
public void start(Stage primaryStage) throws Exception {
ListView<Integer> listView = new ListView<>();
for (int i = 0; i < 100; i++) {
listView.getItems().add(i);
}
CustomSelectionModel<Integer> selectionModel = new CustomSelectionModel<>(listView);
listView.setSelectionModel(selectionModel);
CheckBox moveAllowed = new CheckBox("disallow movement");
moveAllowed.selectedProperty().addListener((o, oldValue, newValue) -> selectionModel.setLeavePredicate(newValue ? (index, item) -> false : null));
CheckBox enterOdd = new CheckBox("enter odd items disallowed");
enterOdd.selectedProperty().addListener((o, oldValue, newValue) -> selectionModel.setEnterPredicate(newValue ? (index, item) -> (index & 1) == 0 : null));
Scene scene = new Scene(new ScrollPane(new HBox(listView, new VBox(moveAllowed, enterOdd))));
primaryStage.setScene(scene);
primaryStage.show();
}