首页 文章

使用TextField的JavaFX TableView过滤器

提问于
浏览
0

我想编写一个方法,我传递一个textfield(filterField),来自tableview(数据)和tableview(表)的数据,以便过滤所有的表数据,检查每次在文本字段中释放一个键,如果字符串typed包含在表的任何单元格中 .

此方法是通用的,用于具有不同列 Headers 的不同类型的表 .

为此,我使用以下代码:

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

此代码仅在textfield中的字符串与表中任何单元格的值完全匹配时返回值 .

我需要它返回表中包含键入的字符串的任何单元格,即使单元格包含更多字符 . 类似的东西:JavaFX 8 TableView Sorting and Filtering

我还需要它来返回不依赖于小写或大写值的值 .

2 回答

  • 0

    您应该收听 text 属性中的更改,而不是使用 KeyEvent .

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

    请注意,上述代码段均未通知对项目所做的更改 .

  • 1

    本教程很好,并使用TextField的可观察值:textProperty而不是Texfield本身 . 只需根据您的情况进行调整 .

    它会给你较少的耦合,并且正确使用observable,你不会依赖图形事件(如果用户点击并粘贴鼠标而不是键盘怎么办?) - >更健壮

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

相关问题