我写了一个小例子:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MultipleFilterTextfields extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
VBox vbox = new VBox();
TextField firstNameFilterTextField = new TextField();
TextField lastNameFilterTextField = new TextField();
TableView<Person> tableView = new TableView<>();
ObservableList<Person> list = FXCollections.observableArrayList(new Person("Peter", "Schmidt"),
new Person("Hans-Peter", "Schmidt"), new Person("Hans", "Mustermann"));
FilteredList<Person> filterList = new FilteredList<>(list);
tableView.setItems(filterList);
TableColumn<Person, String> firstNameCol = new TableColumn<>("FirstName");
TableColumn<Person, String> lastNameCol = new TableColumn<>("LastName");
firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));
lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));
firstNameFilterTextField.textProperty().addListener((obsVal, oldValue, newValue) -> {
filterList.setPredicate(person -> person.getFirstName().contains(newValue));
});
lastNameFilterTextField.textProperty().addListener((obsVal, oldValue, newValue) -> {
filterList.setPredicate(person -> person.getLastName().contains(newValue));
});
tableView.getColumns().addAll(firstNameCol, lastNameCol);
vbox.getChildren().addAll(firstNameFilterTextField, lastNameFilterTextField, tableView);
Scene scene = new Scene(vbox, 250, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public class Person {
private String firstName;
private String lastName;
public Person(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
public static void main(String[] args) {
launch(args);
}
}
看起来像这样:
在tableView
之上有两个TextField
,一个用于过滤firstName
,另一个用于过滤lastName
。他们每个人都会过滤整个tableView
:
如果我输入第一个字段:“Hans”,表格会过滤两个人“Hans-Peter Schmidt”和“Hans Mustermann”。如果我在第二个中键入“Schmidt”,它会过滤“Peter Schmidt”和“Hans-Peter Schmidt”。
问题是,我无法同时过滤(使用上面的代码)firstName
和lastName
。
你有什么想法吗?
感谢您的帮助!
答案 0 :(得分:2)
怎么样
filteredList.predicateProperty().bind(Bindings.createObjectBinding(() ->
person -> person.getFirstName().contains(firstNameFilterTextField.getText())
&& person.getLastName().contains(lastNameFilterTextField.getText()),
firstNameFilterTextField.textProperty(),
lastNameFilterTextField.textProperty()
));
而不是文本字段上的两个侦听器。
Bindings.createObjectBinding(...)
接受一个生成计算值的函数,以及绑定必须遵守的任何属性的列表。在这种情况下,如果任一文本字段发生更改,我们希望重新计算,因此属性列表是两个文本字段的文本属性。
该函数必须返回谓词,因此它的格式为() -> predicate
。
谓词本身是将Person
映射到boolean
的函数,因此谓词看起来像person -> condition
,第一个参数的整体形式是
() -> person -> condition
请注意,您仍然可以使用两个侦听器执行此操作:
firstNameFilterTextField.textProperty().addListener((obsVal, oldValue, newValue) -> {
filterList.setPredicate(person -> person.getFirstName().contains(firstNameFilterTextField.getText())
&& person.getLastName().contains(lastNameFilterTextField.getText()));
});
lastNameFilterTextField.textProperty().addListener((obsVal, oldValue, newValue) -> {
filterList.setPredicate(person -> person.getFirstName().contains(firstNameFilterTextField.getText())
&& person.getLastName().contains(lastNameFilterTextField.getText()));
});
但单一绑定似乎更优雅(对我而言)。