Как сделать поиск элементов в ListSelectionView (JavaFX)?

Мне нужно реализовать поиск в компоненте ListSelectionView из ControlsFX. И для списка "available", и для списка "selected", но основная проблема следующая - при сбросе текста в TextField, список возвращается к первоначальному виду.

Пробовал найти в документации, пробовал нейронку, вообщем искал везде, но нашёл лишь вариант с FilteredList.

Мой код:

public class selectionViewController implements Initializable {

    @FXML
    private TextField listSearchAvailable;

    @FXML
    private TextField listSearchSelected;

    @FXML
    private ListSelectionView<RetailStore> listSelectionView;

    private ObservableList<RetailStore> availableRetailStores;

    private FilteredList<RetailStore> filteredList;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        availableRetailStores = FXCollections.observableArrayList();
        loadData();
        searchHandler();
    }
    
    private void loadData() {
        // ЗАГРУЖАЮ ДАННЫЕ
        // И ИНИЦИАЛИЗИРУЮ ВСЕ СПИСКИ

        List<RetailStore> retailStores = this.skladRequest.getRetailStoresFromSklad(node);
        ObservableList<RetailStore> observableRetailStores = FXCollections.observableArrayList();
        observableRetailStores.addAll(retailStores);
        listSelectionView.setSourceItems(observableRetailStores);
        availableRetailStores.addAll(listSelectionView.getSourceItems());

        filteredList = new FilteredList<>(availableRetailStores, p -> true);
        listSelectionView.setSourceItems(filteredList);

    }
    
    // САМ МЕТОД ПОИСКА
    private void searchHandler() {
        listSearchAvailable.textProperty().addListener((obs, oldVal, newVal) -> {
            String lower = (newVal == null) ? "" : newVal.toLowerCase();
            filteredList.setPredicate(store -> store.getName().toLowerCase().contains(lower));
        });
    }

При таком варианте список возвращается к исходному виду каждый раз. Вероятно нужно добавить ещё какой-то список, через который обрабатывать это всё, но что-то не получается придумать как.


Ответы (1 шт):

Автор решения: Лавров Никита

Ввёл 2 отдельные переменные для выбранных и оставшихся списков

private final ObservableList<RetailStore> availableRetailStores = FXCollections.observableArrayList();
private final ObservableList<RetailStore> selectedRetailStores = FXCollections.observableArrayList();

Отдельно через них фильтрую и обновляю списки

private void filterAvailableList(String filter) {
    availableRetailStores.clear();
    String lowerFilter = filter == null ? "" : filter.toLowerCase();
    List<RetailStore> filtered = retailStores.stream()
        .filter(store -> store.getName().toLowerCase().contains(lowerFilter))
        .filter(store -> !selectedRetailStores.contains(store))
        .collect(Collectors.toList());

    availableRetailStores.addAll(filtered);
}

Затем использую в слушателе на TextField

private void searchAvailable() {
    listSearchAvailable.textProperty().addListener((obs, oldVal, newVal) -> {
        filterAvailableList(newVal);
    });
}

В init обновляю списки, которые выводятся и вызываю методы фильтрации

@Override
public void initialize(URL location, ResourceBundle resources) {
    listSelectionView.setSourceItems(availableRetailStores);
    listSelectionView.setTargetItems(selectedRetailStores);

    searchAvailable();
    searchSelected();
}
→ Ссылка