Фильтр JavaFX TableView с использованием TextField - PullRequest
0 голосов
/ 05 сентября 2018

Я хочу закодировать метод, в котором я передаю текстовое поле (filterField), данные из таблицы (данные) и таблицы (таблица), чтобы отфильтровать все данные таблицы, проверяя каждый раз, когда ключ освобождается в текстовом поле, если введенная строка содержится в любой ячейке таблицы.

Этот метод должен быть универсальным и использоваться для разных типов таблиц с разными заголовками столбцов.

Для этого я использую следующий код:

public void addTextFilter(ObservableList<List<Object>> allData, 
                           JFXTextField filterField, TableView<List<Object>> table) {

    FilteredList<List<Object>> filteredData  = new FilteredList<>(allData, p -> true);
    filterField.setOnKeyReleased(e -> 
    {
         filteredData.setPredicate(p  -> 
         {
             if (filterField.getText() == null || filterField.getText().isEmpty()){
                 return true;
             }else {
                 return p.contains(filterField.getText()); 
             }
         });


    });

    SortedList<List<Object>> sortedData = new SortedList<>(filteredData);
    sortedData.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedData);
}

Этот код возвращает значения только тогда, когда строка в текстовом поле точно соответствует значению любой ячейки в таблице.

Мне нужно было бы вернуть любую ячейку таблицы, которая содержит напечатанную в ней строку при вводе, даже если эта ячейка содержит больше символов. Нечто похожее на это: JavaFX 8 TableView Сортировка и фильтрация

Мне также нужно, чтобы он возвращал значения, не зависящие от строчных или прописных значений.

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Вместо использования KeyEvent вам следует прослушать изменения в свойстве text.

TableColumn s можно использовать для извлечения значений для ячеек, которые можно использовать в предикате.

public static <T> void addTextFilter(ObservableList<T> allData,
        JFXTextField filterField, TableView<T> table) {

    final List<TableColumn<T, ?>> columns = table.getColumns();

    FilteredList<T> filteredData = new FilteredList<>(allData);
    filteredData.predicateProperty().bind(Bindings.createObjectBinding(() -> {
        String text = filterField.getText();

        if (text == null || text.isEmpty()) {
            return null;
        }
        final String filterText = text.toLowerCase();

        return o -> {
            for (TableColumn<T, ?> col : columns) {
                ObservableValue<?> observable = col.getCellObservableValue(o);
                if (observable != null) {
                    Object value = observable.getValue();
                    if (value != null && value.toString().toLowerCase().equals(filterText)) {
                        return true;
                    }
                }
            }
            return false;
        };
    }, filterField.textProperty()));

    SortedList<T> sortedData = new SortedList<>(filteredData);
    sortedData.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedData);
}

Если ваши столбцы содержат значения списка, вы можете немного упростить код:

public static void addTextFilter(ObservableList<List<Object>> allData,
        JFXTextField filterField, TableView<List<Object>> table) {

    final List<TableColumn<List<Object>, ?>> columns = table.getColumns();

    FilteredList<List<Object>> filteredData = new FilteredList<>(allData);
    filteredData.predicateProperty().bind(Bindings.createObjectBinding(() -> {
        String text = filterField.getText();

        if (text == null || text.isEmpty()) {
            return null;
        }
        final String filterText = text.toLowerCase();

        return o -> {
            for (Object value : columns) {
                if (value != null && value.toString().toLowerCase().equals(filterText)) {
                    return true;
                }
            }
            return false;
        };
    }, filterField.textProperty()));

    SortedList<List<Object>> sortedData = new SortedList<>(filteredData);
    sortedData.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedData);
}

Обратите внимание, что ни один из приведенных выше фрагментов кода не уведомляется об изменениях, внесенных в элементы.

0 голосов
/ 05 сентября 2018

Урок хорош и использует наблюдаемое значение TextField: textProperty вместо самого Texfield. Просто приспособьте его к вашему делу.

Это даст вам меньшую связь и правильное использование наблюдаемого, вы не будете полагаться на графическое событие (что если пользователь щелкнет и вставит мышь вместо клавиатуры?) -> более надежный

public void addTextFilter(ObservableList<List<Object>> allData, 
                       StringProperty textProperty, TableView<List<Object>> table)     {


  FilteredList<List<Object>> filteredData  = new FilteredList<>(allData, p -> true);
  // Use textProperty
  textProperty.addListener((observable, oldValue, newValue) -> {
        filteredData.setPredicate(person -> {
            // If filter text is empty, display all persons.
            if (newValue == null || newValue.isEmpty()) {
                return true;
            }

            // Compare first name and last name of every person with filter text.
            String lowerCaseFilter = newValue.toLowerCase();

            if (person.getFirstName().toLowerCase().contains(lowerCaseFilter)) {
                return true; // Filter matches first name.
            } else if     (person.getLastName().toLowerCase().contains(lowerCaseFilter)) {
                return true; // Filter matches last name.
            }
            return false; // Does not match.
        });
    });

  SortedList<List<Object>> sortedData = new SortedList<>(filteredData);
  sortedData.comparatorProperty().bind(table.comparatorProperty());
  table.setItems(sortedData);
}
...