JavaFX - 多个文本字段应该过滤一个表格 View

标签 java javafx

我写了一个小例子:

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

看起来像这样:

enter image description here

tableView上面有两个TextField,一个用来过滤firstName,另一个用来过滤lastName。它们每个都过滤整个 tableView:

如果我在第一个字段中键入:“Hans”,该表会过滤两个人“Hans-Peter Schmidt”和“Hans Mustermann”。如果我在第二个中输入“Schmidt”,它会过滤“Peter Schmidt”和“Hans-Peter Schmidt”。

问题是,我无法同时过滤(使用上面的代码)firstNamelastName

你有什么想法吗?

感谢您的帮助!

最佳答案

怎么样

filteredList.predicateProperty().bind(Bindings.createObjectBinding(() ->
    person -> person.getFirstName().contains(firstNameFilterTextField.getText())
           && person.getLastName().contains(lastNameFilterTextField.getText()),

    firstNameFilterTextField.textProperty(),
    lastNameFilterTextField.textProperty()

));

而不是文本字段上的两个监听器。

Bindings.createObjectBinding(...) 采用生成计算值的函数,以及绑定(bind)必须遵守的任何属性的列表。在这种情况下,如果任一文本字段发生更改,我们希望重新计算,因此属性列表是两个文本字段的文本属性。

该函数必须返回一个谓词,所以它的形式是 () -> 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()));
    });

但单一绑定(bind)似乎更优雅(对我而言)。

关于JavaFX - 多个文本字段应该过滤一个表格 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33016064/

相关文章:

java - 未能获得 JDK 11、Spring Boot(包括)的组合。持久性和 JavaFX 工作

java - 如何使用绑定(bind)使 JavaFX TextField 中的文本自动更改?

java - 使用java从32位二进制补码转换为十进制

java - 我不断收到错误 : incomparable types: int and string

java - Java Concurrency 中的示例在实践中如何保证线程安全

JavaFX 渲染/图像处理

JavaFx:如何使用 scenebuilder 制作可点击的图像

java - KML 在未挤压时出现线性环的高度问题

java - 正则表达式不适用于替换特殊字符

java - Switch 语句关键事件为 1