【问题标题】:JavaFX tableview search filter not working, but no errors?JavaFX tableview 搜索过滤器不起作用,但没有错误?
【发布时间】:2018-12-17 18:39:32
【问题描述】:

我正在创建一个程序来存储 999 份报告。我正在尝试按以下三种服务过滤这些报告:警察、医疗和消防。我试图通过过滤器搜索来做到这一点,使用 TextField 来做到这一点。我已经按照教程进行操作,但是对我来说它们不起作用。

我已经查看了我的代码,试图改变一些东西,但我仍然无法让它工作。我希望这里的人可能知道我到底做错了什么,以及如何解决它。

public class EmergencyReports extends Application {
    Stage window;
    TableView<Report> table;
    ObservableList<Report> Reports = FXCollections.observableArrayList();
    TextField dateInput, timeInput, firstNameInput, lastNameInput, locationInput, issueInput, policeInput, fireInput, medicalInput, searchInput;

    public static void main(String[]args){
        launch(args);

    }

    @Override
    public void start (Stage primaryStage) throws Exception {
        window = primaryStage;
        window.setTitle("Emergency Operator Pannel");

        //Columns created here!
    TableColumn<Report,String> responseRequestedCol = new TableColumn<>("Response Requested (P/M/F)");
        responseRequestedCol.setMinWidth(200);
            responseRequestedCol.setCellValueFactory(new PropertyValueFactory<Report, String>("responseRequested"));
    TableColumn dateCol = new TableColumn("Date (DD/MM/YY)");
        dateCol.setMinWidth(25);
            dateCol.setCellValueFactory(new PropertyValueFactory<Report, String>("date"));
    TableColumn timeCol = new TableColumn("Time (HH:MM)");
        timeCol.setMinWidth(25);
            timeCol.setCellValueFactory(new PropertyValueFactory<Report, String>("time"));
    TableColumn firstNameCol = new TableColumn("First Name");
        firstNameCol.setMinWidth(50);
                firstNameCol.setCellValueFactory(new PropertyValueFactory<Report, String>("firstName"));
    TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(50);
                lastNameCol.setCellValueFactory(new PropertyValueFactory<Report, String>("lastName"));
    TableColumn locationCol = new TableColumn("Location");
        locationCol.setMinWidth(200);
                locationCol.setCellValueFactory(new PropertyValueFactory<Report, String>("location"));
    TableColumn issueCol = new TableColumn("Issue");
        issueCol.setMinWidth(600);
                issueCol.setCellValueFactory(new PropertyValueFactory<Report, String>("issue"));
    TableColumn policeCol = new TableColumn("Police");
        policeCol.setMinWidth(25);
                policeCol.setCellValueFactory(new PropertyValueFactory<Report, String>("police"));
    TableColumn medicalCol = new TableColumn("Medical");
        medicalCol.setMinWidth(25);
                medicalCol.setCellValueFactory(new PropertyValueFactory<Report, String>("medical"));
    TableColumn fireCol = new TableColumn("Fire");
        fireCol.setMinWidth(25);
                fireCol.setCellValueFactory(new PropertyValueFactory<Report, String>("fire"));
    //Nested Column for emergency services      
    responseRequestedCol.getColumns().addAll(policeCol, medicalCol, fireCol);

    //Creation of TextFields
        //Date TextFields here
        searchInput = new TextField();
        searchInput.setPromptText("Search Response Type");
        searchInput.setMinWidth(25);

        dateInput = new TextField();
        dateInput.setPromptText("Date");
        dateInput.setMinWidth(25);

        //Time TextFields here
        timeInput = new TextField();
        timeInput.setPromptText("Time");
        timeInput.setMinWidth(25);

        //First Name TextFields here
        firstNameInput = new TextField();
        firstNameInput.setPromptText("First Name");
        firstNameInput.setMinWidth(25);

        //Last Name TextFields here
        lastNameInput = new TextField();
        lastNameInput.setPromptText("Last Name");
        lastNameInput.setMinWidth(25);

        //Location TextFields here
        locationInput = new TextField();
        locationInput.setPromptText("Location");
        locationInput.setMinWidth(25);

        //Issue TextFields here
        issueInput = new TextField();
        issueInput.setPromptText("Issue");
        issueInput.setMinWidth(25);

        //Police TextFields here
        policeInput = new TextField();
        policeInput.setPromptText("Police");
        policeInput.setMinWidth(25);

        //Fire TextFields here
        fireInput = new TextField();
        fireInput.setPromptText("Fire");
        fireInput.setMinWidth(25);

        //Medical TextFields here
        medicalInput = new TextField();
        medicalInput.setPromptText("Medical");
        medicalInput.setMinWidth(25);

        //Buttons and Lambda exoressions
        Button addButton = new Button("Add");
        addButton.setOnAction(e ->addButtonClicked());
        Button deleteButton = new Button("Delete");
        deleteButton.setOnAction(e ->deleteButtonClicked());
        //Hbox layout for buttons and textfields

        HBox hBox = new HBox();
        HBox hBox1 = new HBox();
        hBox.setPadding(new Insets(10,10,10,10));
        hBox1.setSpacing(10);
        hBox1.setPadding(new Insets(10,10,10,10));
        hBox.setSpacing(10);
        hBox.getChildren().addAll(policeInput, medicalInput, fireInput, dateInput, timeInput);
        hBox1.getChildren().addAll(firstNameInput, lastNameInput, locationInput, issueInput, addButton, deleteButton, searchInput);

    table = new TableView<>();
    table.setItems(getReport());
    table.getColumns().addAll(responseRequestedCol,dateCol,timeCol,firstNameCol,lastNameCol,locationCol,issueCol);

        VBox vBox = new VBox();
        vBox.getChildren().addAll(table,hBox, hBox1);

【问题讨论】:

  • 即使对于 lambda 表达式,您也应该使用相同的命名约定。我花了一段时间才能正确读取 lambda 代码,因为您的变量 Report 被着色为一个类。

标签: java javafx tableview


【解决方案1】:

第一期

我不确定Reports 字段是否已正确初始化。将其初始化为空ObservableList,但初始列表是使用getReport 创建的。

第二期

您将侦听器注册到同一 TextFieldonKeyReleased 方法内的 text 属性。不应该这样做。 text 属性只在文本时更新,不需要KeyEvents 的处理程序。


编辑

FilteredList<Report> filteredReports = new FilteredList<>(getReport());
searchInput.textProperty().addListener((observavleValue, oldValue, newValue) -> {
    if (newValue == null || newValue.isEmpty()) { // check necessary only once
        filteredReports.setPredicate(null); // equivalent to setting (i->true)
    } else {
        final String lowerCaseFilter = newValue.toLowerCase();

        filteredReports.setPredicate((Predicate<? super Report>) Report -> {
            return Report.getPolice().contains(newValue)
                    || Report.getMedical().toLowerCase().contains(lowerCaseFilter)
                    || Report.getFire().toLowerCase().contains(lowerCaseFilter);
        });
    }
});
SortedList<Report> sortedReports = new SortedList<>(filteredReports);
sortedReports.comparatorProperty().bind(table.comparatorProperty());
table.setItems(sortedReports);

所有Application类都需要显示表格/TextField:

@Override
public void start(Stage primaryStage) throws Exception {
    TableView<Report> table = new TableView<>();
    
    TableColumn<Report, String> policeCol = new TableColumn<>("Police");
    policeCol.setCellValueFactory(new PropertyValueFactory<>("police"));
    TableColumn<Report, String> medicalCol = new TableColumn<>("Medical");
    medicalCol.setCellValueFactory(new PropertyValueFactory<>("medical"));
    TableColumn<Report, String> fireCol = new TableColumn<>("Fire");
    fireCol.setCellValueFactory(new PropertyValueFactory<>("fire"));
    table.getColumns().addAll(policeCol, medicalCol, fireCol);

    TextField searchInput = new TextField();
    searchInput.setPromptText("Search Response Type");

    // Creation of Search function created here - search via requested service
    FilteredList<Report> filteredReports = new FilteredList<>(getReport());
    searchInput.textProperty().addListener((observavleValue, oldValue, newValue) -> {
        if (newValue == null || newValue.isEmpty()) { // check necessary only once
            filteredReports.setPredicate(null); // equivalent to setting (i->true)
        } else {
            final String lowerCaseFilter = newValue.toLowerCase();

            filteredReports.setPredicate((Predicate<? super Report>) Report -> {
                return Report.getPolice().contains(newValue)
                        || Report.getMedical().toLowerCase().contains(lowerCaseFilter)
                        || Report.getFire().toLowerCase().contains(lowerCaseFilter);
            });
        }
    });
    SortedList<Report> sortedReports = new SortedList<>(filteredReports);
    sortedReports.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedReports);

    Scene scene = new Scene(new VBox(table, searchInput));
    primaryStage.setScene(scene);
    primaryStage.show();
}

public ObservableList<Report> getReport() {
    ObservableList<Report> Reports = FXCollections.observableArrayList();
    Reports.addAll(new Report("ab", "cd", "ef"), new Report("bc", "de", "fg"));
    return Reports;
}

public static class Report {

    private final String fire;
    private final String police;
    private final String medical;

    public Report(String police, String fire, String medical) {
        super();
        this.police = police;
        this.fire = fire;
        this.medical = medical;
    }

    public String getFire() {
        return fire;
    }

    public String getPolice() {
        return police;
    }

    public String getMedical() {
        return medical;
    }

}

【讨论】:

  • 这不起作用。我已经在上面添加了我的整个班级。也许您可以看到的其他地方有问题?
  • @Shawn 你检查过@fabian 的第一点吗?您的Reports 对象永远不会被填充,您的getReport() 方法会创建一个局部变量Reports 并在不更改任何成员变量Reports 的情况下返回它,因此当您调用FilteredList&lt;Report&gt; filteredReports = new FilteredList(Reports, e -&gt;true) 时,它不会按照您的想法进行它应该这样做,filteredReports 对象是一个空列表的副本,这也使它成为一个空列表。 fabian 实际上在他的第二点中稍微修改了这部分,但我看到你没有按照编辑的方式复制它。
  • @Shawn:复制您的代码,创建我自己的 Report 类,其中仅包含 3 个相关属性,删除其他列并用我的答案中的代码替换 FilteredList 创建 + 注册监听器对我有用(假设我更改了 getReport 方法以返回更有趣的内容)。
  • 我不明白。您可以发布您创建的代码,以便我查看和比较。我按照教程制作了这个程序(根据我的需要进行调整),它适用于其他人。
  • 好的,我添加了一些代码,但删除了所有与问题无关的不必要的东西。
【解决方案2】:

您可以直接向Text 属性添加侦听器,而无需侦听文本字段上的按键事件。尝试替换:

 searchInput.setOnKeyReleased(e ->{
    searchInput.textProperty().addListener((observavleValue, oldValue, newValue) -> {
        filteredReports.setPredicate((Predicate<? super Report>) Report->{
            if (newValue == null || newValue.isEmpty()){
                return true;
            }
            String lowerCaseFilter = newValue.toLowerCase();
            if(Report.getPolice().contains(newValue)){
                return true;
            }else if(Report.getMedical().toLowerCase().contains(lowerCaseFilter)){
                return true;
            }else if(Report.getFire().toLowerCase().contains(lowerCaseFilter)){
                return true;
            }
            return false;
        });
    });
    SortedList<Report> sortedReports = new SortedList<>(filteredReports);
    sortedReports.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedReports);
});

与:

searchInput.textProperty().addListener((observavleValue, oldValue, newValue) -> {
    filteredReports.setPredicate((Predicate<? super Report>) Report->{
        if (newValue == null || newValue.isEmpty()){
            return true;
        }
        String lowerCaseFilter = newValue.toLowerCase();
        if(Report.getPolice().contains(newValue)){
            return true;
        }else if(Report.getMedical().toLowerCase().contains(lowerCaseFilter)){
            return true;
        }else if(Report.getFire().toLowerCase().contains(lowerCaseFilter)){
            return true;
        }
        return false;
    });

    SortedList<Report> sortedReports = new SortedList<>(filteredReports);
    sortedReports.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedReports);
});

【讨论】:

  • 这不起作用。我已经在上面添加了我的整个班级。也许您可以看到的其他地方有问题?
猜你喜欢
  • 2015-03-12
  • 2018-08-23
  • 2018-11-28
  • 2016-08-04
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-02
相关资源
最近更新 更多