JavaFX 项目中的搜索栏问题(javaFX + h2 数据库,“总计”文本字段不适用于搜索栏),CRUD

问题描述 投票:0回答:1

我的 JavaFX 项目有问题。我有一个可与我的

TableView
配合使用的搜索栏。我创建了一个“总计”
TextField
,它应该显示表中所有记录的总数。但我的意思是所有记录,我的意思是所有记录,例如在使用搜索栏过滤记录之后。目前,当我使用搜索栏过滤表记录时,“总计”
TextField
仍然显示数据库中此列中所有记录的总值,而不是当前在
TableView
中的所有记录。你能看一下并帮我找出我应该做什么才能让它发挥作用吗?

这是我的代码:

private void searchData() {
    FilteredList<Data> filteredData = new FilteredList<>(getDataList(), b -> true);
    search.textProperty().addListener((observable, oldValue, newValue) -> filteredData.setPredicate(Data -> {
        if(newValue.isEmpty() || newValue.isBlank()) {
            return true;
        }
        String lowerCase = newValue.toLowerCase();
        if(Data.getName().toLowerCase().contains(lowerCase)) {
            return true;
        }
        else if(Data.getCategory().toLowerCase().contains(lowerCase)) {
            return true;
        }
        else if(String.valueOf(Data.getPrice()).toLowerCase().contains(lowerCase)) {
            return true;
        }
        else
            return String.valueOf(Data.getDate()).toLowerCase().contains(lowerCase);
    }));
    SortedList<Data> sortedData = new SortedList<>(filteredData);
    sortedData.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedData);
    total();
}

private void total() {
    int totalAmount = 0;
    totalAmount = table.getItems()
                       .stream()
                       .map((item) -> item.getPrice())
                       .reduce(totalAmount, (accumulation, _item) -> accumulation + _item);
    total.setText(String.valueOf(totalAmount));
}

编辑1:

private void searchData() {
        FilteredList<Data> filteredData = new FilteredList<>(getDataList(), b -> true);
        search.textProperty().addListener((observable, oldValue, newValue) -> filteredData.setPredicate(Data -> {

            if(newValue.isEmpty() || newValue.isBlank()) {
                total();
                return true;
            }
            String lowerCase = newValue.toLowerCase();

            if(Data.getName().toLowerCase().contains(lowerCase)) {
                total();
                return true;
            }
            else if(Data.getCategory().toLowerCase().contains(lowerCase)) {
                total();
                return true;
            }
            else if(String.valueOf(Data.getPrice()).toLowerCase().contains(lowerCase)) {
                total();
                return true;
            }
            else if(String.valueOf(Data.getDate()).toLowerCase().contains(lowerCase)) {
                total();
                return true;
            }
            else return false;
        }));
        SortedList<Data> sortedData = new SortedList<>(filteredData);
        sortedData.comparatorProperty().bind(table.comparatorProperty());
        table.setItems(sortedData);
    }
javafx h2
1个回答
0
投票

在第一次尝试编写代码时,当您使用搜索字段的文本属性注册侦听器时,只需调用

total()
一次。
total()
方法永远不会被再次调用,因此当表中的项目发生变化时,总数不会更新。

在第二次尝试中,您在实际谓词内调用

total()
,用于确定元素是否应包含在过滤列表中。你实际上不知道这些谓词何时会被执行:这是
FilteredList
的内部实现细节。谓词应该简单地返回
true
false
,具体取决于元素是否应包含在列表中;这些方法有副作用是没有意义的。

每次数据变化时都需要重新计算总数。执行此操作的一种方法(假设您没有在其他地方更改数据)是简单地在侦听器中调用

total()
来更改搜索字段的文本属性:

private void searchData() {
    FilteredList<Data> filteredData = new FilteredList<>(getDataList(), b -> true);
    search.textProperty().addListener((observable, oldValue, newValue) -> {
        filteredData.setPredicate(Data -> {
            if(newValue.isEmpty() || newValue.isBlank()) {
                return true;
            }
            String lowerCase = newValue.toLowerCase();
            if(Data.getName().toLowerCase().contains(lowerCase)) {
                return true;
            }
            else if(Data.getCategory().toLowerCase().contains(lowerCase)) {
                return true;
            }
            else if(String.valueOf(Data.getPrice()).toLowerCase().contains(lowerCase)) {
                return true;
            }
            else
                return String.valueOf(Data.getDate()).toLowerCase().contains(lowerCase);

        });

        total();

    });

    SortedList<Data> sortedData = new SortedList<>(filteredData);
    sortedData.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedData);
    total();
}

您不会在其他地方更改数据的假设可能太大了。 (例如,即使您现在不这样做,您也可能希望添加功能以将新数据添加到表中,在这种情况下,当您添加新数据时,总数不会更新。)更好的方法是注册侦听器或与列表的绑定。 (这假设您没有在代码中的其他任何地方调用

table.setItems()
,但在大多数情况下这是一个合理的假设。)

你可以做

private void searchData() {
    FilteredList<Data> filteredData = new FilteredList<>(getDataList(), b -> true);
    search.textProperty().addListener((observable, oldValue, newValue) -> {
        filteredData.setPredicate(Data -> {
            if(newValue.isEmpty() || newValue.isBlank()) {
                return true;
            }
            String lowerCase = newValue.toLowerCase();
            if(Data.getName().toLowerCase().contains(lowerCase)) {
                return true;
            }
            else if(Data.getCategory().toLowerCase().contains(lowerCase)) {
                return true;
            }
            else if(String.valueOf(Data.getPrice()).toLowerCase().contains(lowerCase)) {
                return true;
            }
            else
                return String.valueOf(Data.getDate()).toLowerCase().contains(lowerCase);

        });

    });

    SortedList<Data> sortedData = new SortedList<>(filteredData);
    sortedData.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedData);

    sortedData.addListener((ListChangeListener.Change<? extends Data> c) -> total());
    total();
}

或带有装订:

private void searchData() {
    FilteredList<Data> filteredData = new FilteredList<>(getDataList(), b -> true);
    search.textProperty().addListener((observable, oldValue, newValue) -> {
        filteredData.setPredicate(Data -> {
            if(newValue.isEmpty() || newValue.isBlank()) {
                return true;
            }
            String lowerCase = newValue.toLowerCase();
            if(Data.getName().toLowerCase().contains(lowerCase)) {
                return true;
            }
            else if(Data.getCategory().toLowerCase().contains(lowerCase)) {
                return true;
            }
            else if(String.valueOf(Data.getPrice()).toLowerCase().contains(lowerCase)) {
                return true;
            }
            else
                return String.valueOf(Data.getDate()).toLowerCase().contains(lowerCase);

        });

    });

    SortedList<Data> sortedData = new SortedList<>(filteredData);
    sortedData.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(sortedData);

    total.textProperty().bind(Bindings.createStringBinding(
        this::total,
        sortedData
    ));
}

绑定版本需要对

total()
方法进行小修改:

private String total() {
    int totalAmount = table.getItems()
                       .stream()
                       //.map((item) -> item.getPrice())
                       //.reduce(totalAmount, (accumulation, _item) -> accumulation + _item);
                       // simplified code:
                       .collect(Collectors.summingDouble(Data::getPrice));
    return String.valueOf(totalAmount);
}
© www.soinside.com 2019 - 2024. All rights reserved.