我想编写一个方法,我传递一个文本字段(filterField),一个表视图(data)和表视图(table)中的数据,以便过滤所有表数据,并检查每次在该文本字段中释放键时,如果键入的字符串包含在表的任何单元格中。
此方法是通用的,可用于具有不同列标题的不同类型的表。
为此,我正在使用以下代码:
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 Sorting and Filtering
我还需要它返回不依赖于小写或大写值的值。
答案 0 :(得分:1)
您应该听KeyEvent
属性中的更改,而不是使用text
。
TableColumn
可用于检索可在谓词中使用的单元格的值。
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 :(得分:0)
本教程很好,并使用了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);
}
答案 2 :(得分:0)
我为此感到非常自豪,我认为这是我第一次回答有关StackOverflow的问题。
此代码将允许您搜索部分匹配项。因此,如果您输入字母d
,它将消除没有字母d的任何行。
此代码还将允许您在表的每一行中搜索多个单词(用空格分隔)。因此,如果单词“ dog”和“ woof”都在行,那么您将输入:
狗叫
它将仅显示具有两个单词的行。您可以根据需要使用任意多个搜索词。
public static void addTextFilterB(ObservableList<List<Object>> allData,
TextField 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 {
String pToString = p.toString().toLowerCase().replace(", "," ");
String textIwantB = filterField.getText();
String[] parts = textIwantB.toLowerCase().split(" ");
if(p.contains(textIwantB)){
System.out.println("p.: " + p);
}
int counter = 0;
for (int i = 0; i < parts.length; i ++) {
if (parts[i] != null)
if(!(pToString.contains(parts[i]))){
System.out.println("this one is eliminated: " + pToString);
return false;
}
counter++;
}
System.out.println("counter: " + counter);
return pToString.contains(parts[0]);
}
});
});
SortedList<List<Object>> sortedData = new SortedList<>(filteredData);
sortedData.comparatorProperty().bind(table.comparatorProperty());
table.setItems(sortedData);
}