Как посчитать количество элементов в TableView, которые соответствуют указанному значению / строке - PullRequest
0 голосов
/ 15 сентября 2018

Итак, у меня есть TableView с функцией фильтрации и несколько Labels для отображения результата.

x человек найдено, x являются VIP / NON VIP и т. Д.

Теперь я пытаюсь подсчитать количество элементов, которые соответствуют указанному значение / строка в моем TableView, чтобы обновить текст x на Labels и отобразить его как результат.(результат должен отображаться и обновляться автоматически при изменении элементов в TableView без выбора строк или столбцов).

Для Label всего человека, которого я уже сделал с table.getItems().size(), так что есть еще 3идти.Моя идея состоит в том, чтобы создать переменную string / int внутри for loop и сравнить ее с элементами в TableView, а затем обернуть ее в listener, чтобы она автоматически обновляла Labels, но я не знаю,это возможно или нет.

Вот мой код, и вам нужно добавить controlsfx jar из здесь .В настоящее время я помещаю все Labels в метод «чистой» кнопки, чтобы обновить его вручную.

MainApp

import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import org.controlsfx.control.CheckComboBox;


public class MainApp extends Application {
    @Override
    public void start(Stage primaryStage) {
        TableView<Person> table = new TableView<>();
        table.getSelectionModel().setCellSelectionEnabled(true);
        table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        table.getColumns().add(column("Name", Person::nameProperty));
        table.getColumns().add(column("Email", Person::emailProperty));
        table.getColumns().add(column("Gender", Person::genderProperty));
        table.getColumns().add(column("Birthday", Person::birthdayProperty));
        table.getColumns().add(column("Age", Person::ageProperty));
        table.getColumns().add(column("Status", Person::statusProperty));

        ComboBox<Person.Gender> genderFilterCombo = new ComboBox<>();
        genderFilterCombo.getItems().addAll(Person.Gender.values());

        CheckComboBox<Person.Gender> genderFilterCheckCombo= new CheckComboBox<>();
        genderFilterCheckCombo.getItems().addAll(Person.Gender.values());

        CheckComboBox<Person.Status> statusFilterCheckCombo= new CheckComboBox<>();
        statusFilterCheckCombo.getItems().addAll(Person.Status.values());

        TextField nameFilterField = new TextField();
        TextField agefromFilterField = new TextField();
        TextField ageuntilFilterField = new TextField();
        DatePicker datefromFilterField = new DatePicker();
        DatePicker dateuntilFilterField = new DatePicker();

        Label totalperson = new Label();
        Label totalvip = new Label();
        Label totaloldperson = new Label();
        Label totalyoungperson = new Label();

        nameFilterField.setPromptText("Name");
        agefromFilterField.setPromptText("Age from");
        ageuntilFilterField.setPromptText("Age until");
        datefromFilterField.setPromptText("Birthday from");
        dateuntilFilterField.setPromptText("Birthday until");

        ObjectProperty<Predicate<Person>> nameFilter = new SimpleObjectProperty<>();
        ObjectProperty<Predicate<Person>> genderFilter = new SimpleObjectProperty<>();
        ObjectProperty<Predicate<Person>> gender2Filter = new SimpleObjectProperty<>();
        ObjectProperty<Predicate<Person>> datefromFilter = new SimpleObjectProperty<>();
        ObjectProperty<Predicate<Person>> dateuntilFilter = new SimpleObjectProperty<>();
        ObjectProperty<Predicate<Person>> agefromFilter = new SimpleObjectProperty<>();
        ObjectProperty<Predicate<Person>> ageuntilFilter = new SimpleObjectProperty<>();
        ObjectProperty<Predicate<Person>> statusFilter = new SimpleObjectProperty<>();

        nameFilter.bind(Bindings.createObjectBinding(() ->
                        person -> person.getName().toLowerCase().contains(nameFilterField.getText().toLowerCase()),
                nameFilterField.textProperty()));

        genderFilter.bind(Bindings.createObjectBinding(() ->
                        person -> genderFilterCombo.getValue() == null || genderFilterCombo.getValue() == person.getGender(),
                genderFilterCombo.valueProperty()));

        gender2Filter.bind(Bindings.createObjectBinding(() ->
                genderFilterCheckCombo.getCheckModel().getCheckedItems().isEmpty() ?  person-> true : person->
                        genderFilterCheckCombo.getCheckModel().getCheckedItems().contains(person.getGender()),
                genderFilterCheckCombo.getCheckModel().getCheckedItems()));

        datefromFilter.bind(Bindings.createObjectBinding(() ->
                        person -> datefromFilterField.getValue() == null || datefromFilterField.getValue().isBefore(person.getBirthday())
                                || datefromFilterField.getValue().isEqual(person.getBirthday()),
                datefromFilterField.valueProperty()));

        dateuntilFilter.bind(Bindings.createObjectBinding(() ->
                        person -> dateuntilFilterField.getValue() == null || dateuntilFilterField.getValue().isAfter(person.getBirthday())
                                || dateuntilFilterField.getValue().isEqual(person.getBirthday()),
                dateuntilFilterField.valueProperty()));

        agefromFilter.bind(Bindings.createObjectBinding(() ->
                        person -> agefromFilterField.getText().isEmpty() || Integer.parseInt(agefromFilterField.getText()) <= person.getAge(),
                agefromFilterField.textProperty()));

        ageuntilFilter.bind(Bindings.createObjectBinding(() ->
                        person -> ageuntilFilterField.getText().isEmpty() || Integer.parseInt(ageuntilFilterField.getText()) >= person.getAge(),
                ageuntilFilterField.textProperty()));

        statusFilter.bind(Bindings.createObjectBinding(() ->
                        statusFilterCheckCombo.getCheckModel().getCheckedItems().isEmpty() ?  person-> true : person->
                                statusFilterCheckCombo.getCheckModel().getCheckedItems().contains(person.getStatus()),
                statusFilterCheckCombo.getCheckModel().getCheckedItems()));

        FilteredList<Person> filteredItems = new FilteredList<>(FXCollections.observableList(createData()));
        SortedList<Person> sortedData = new SortedList<>(filteredItems);
        sortedData.comparatorProperty().bind(table.comparatorProperty());
        table.setItems(sortedData);

        filteredItems.predicateProperty().bind(Bindings.createObjectBinding(
                () -> nameFilter.get().and(genderFilter.get().and(gender2Filter.get().and(datefromFilter.get().and(dateuntilFilter.get().
                        and(agefromFilter.get().and(ageuntilFilter.get().and(statusFilter.get()))))))),
                nameFilter, genderFilter, gender2Filter, datefromFilter, dateuntilFilter, agefromFilter, ageuntilFilter, statusFilter));

        Button clear = new Button("Clear Filters");
        clear.setOnAction(e -> {
            /*for (TablePosition<Person, ?> pos : table.getSelectionModel().getSelectedCells()) {
                TableColumn<Person, ?> column = pos.getTableColumn();
                ObservableValue<?> obs = column.getCellObservableValue(pos.getRow());
                Object value = obs.getValue();
                System.out.println(value);
                // process value...
            }*/
            nameFilterField.clear();
            datefromFilterField.setValue(null);
            dateuntilFilterField.setValue(null);

        //Here////////////////////////////////////////////////////////////
        int tp = table.getItems().size();
        totalperson.setText(tp + " " + "persons are found!");
        totalvip.setText("x VIP found!");
        totalyoungperson.setText("x are under or equal 25!");
        totaloldperson.setText("x are over 25!");
        });


        FlowPane filters = new FlowPane( nameFilterField, genderFilterCombo, datefromFilterField, dateuntilFilterField, genderFilterCheckCombo, agefromFilterField,
                ageuntilFilterField, statusFilterCheckCombo, clear);
        HBox labels = new HBox(40, totalperson, totalvip, totalyoungperson, totaloldperson);
        filters.setPadding(new Insets(5));
        labels.setPadding(new Insets(5));
        BorderPane root = new BorderPane(table, filters, null, labels, null);
        Scene scene = new Scene(root, 800, 600);


        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private List<Person> createData() {
        return Arrays.asList(
                new Person("Jacob Smith", "jacob.smith@example.com", Person.Gender.MALE, LocalDate.parse("2018-08-25"),25, Person.Status.NONVIP),
                new Person("Jacob Smith", "jacob.smith@example.com", Person.Gender.MALE, LocalDate.parse("2018-08-26"),24, Person.Status.VIP),
                new Person("Jacob Smith", "jacob.smith@example.com", Person.Gender.FEMALE, LocalDate.parse("2018-08-26"),23, Person.Status.VIP),
                new Person("Jacob Smith", "jacob.smith@example.com", Person.Gender.MALE, LocalDate.parse("2018-08-25"),25, Person.Status.NONVIP),
                new Person("Isabella Johnson", "isabella.johnson@example.com", Person.Gender.FEMALE, LocalDate.parse("2018-08-21"),28, Person.Status.VIP),
                new Person("Ethan Williams", "ethan.williams@example.com", Person.Gender.MALE, LocalDate.parse("2018-08-21"),30, Person.Status.VIP),
                new Person("Emma Jones", "emma.jones@example.com", Person.Gender.FEMALE, LocalDate.parse("2018-08-29"),18, Person.Status.NONVIP),
                new Person("Michael Brown", "michael.brown@example.com", Person.Gender.MALE, LocalDate.parse("2018-08-05"),15, Person.Status.NONVIP)
        );
    }

    public static <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
        TableColumn<S,T> col = new TableColumn<>(title);
        col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
        return col ;
    }


    public static class Person {
//        List<Gender> abc = Arrays.asList(Person.Gender.values());
        public enum Gender {MALE, FEMALE}
        public enum Status {VIP, NONVIP}

        private final StringProperty name = new SimpleStringProperty();
        private final StringProperty email = new SimpleStringProperty() ;
        private final ObjectProperty<Gender> gender = new SimpleObjectProperty<>();
        private final ObjectProperty<LocalDate> birthday = new SimpleObjectProperty<>();
        private final IntegerProperty age = new SimpleIntegerProperty();
        private final ObjectProperty<Status> status = new SimpleObjectProperty<>();

        public Person(String name, String email, Gender gender, LocalDate birthday, Integer age, Status status) {
            setName(name);
            setEmail(email);
            setGender(gender);
            setBirthday(birthday);
            setAge(age);
            setStatus(status);
        }

        public ObjectProperty<Status> statusProperty() { return status; }

        public Status getStatus() { return this.statusProperty().get(); }

        public void setStatus(Status status) { this.statusProperty().set(status); }

        public IntegerProperty ageProperty() { return age; }

        public final int getAge() { return this.ageProperty().get(); }

        public final void setAge(final  Integer age) {this.ageProperty().set(age); }

        public final ObjectProperty<LocalDate> birthdayProperty(){
            return this.birthday;
        }

        public final LocalDate getBirthday() {
            return this.birthdayProperty().get();
        }

        public final void setBirthday(final LocalDate birthday) {
            this.birthdayProperty().set(birthday);
        }

        public final StringProperty emailProperty() {
            return this.email;
        }

        public final String getEmail() {
            return this.emailProperty().get();
        }

        public final void setEmail(final String email) {
            this.emailProperty().set(email);
        }

        public final ObjectProperty<Gender> genderProperty() {
            return this.gender;
        }

        public final Gender getGender() {
            return this.genderProperty().get();
        }

        public final void setGender(final Gender gender) {
            this.genderProperty().set(gender);
        }

        public final StringProperty nameProperty() {
            return this.name;
        }

        public final String getName() { return this.nameProperty().get(); }

        public final void setName(final String name) {
            this.nameProperty().set(name);
        }

    }

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

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

Должно быть возможно решить ваши проблемы, используя чистые привязки JavaFX, используя две конструкции типа:

<some-label>.textProperty().bind(Bindings.size(<observable-list>).asString(<some template>));

Я попытался реализовать минимальный пример (MCVE), чтобы показать число как всех, так иотфильтрованные элементы в таблице.Я не использовал ваши настройки, потому что считал их слишком сложными для MCVE.Я надеюсь, что код довольно понятен, пожалуйста, не стесняйтесь спрашивать, если что-то сбивает с толку или у вас есть проблемы с портированием его на ваш код.

Это приложение имеет минимальный пользовательский интерфейс, который по умолчанию показывает таблицу с двумя записямии две метки, одна сверху (показывает количество всех элементов) и одна снизу (показывает количество элементов, прошедших фильтр).Так как элементы, которые не проходят фильтр, не отображаются, невозможно изменить их, чтобы снова пройти фильтр, поэтому необходимо перезапустить приложение после того, как вы установили флажки или изменили имена (в зависимости от активного фильтра).

Пример представляет собой полноценное приложение JavaFX, вы должны иметь возможность запускать его либо непосредственно из командной строки, либо с любой IDE (например, Eclipse: Run As -> Java Application):

public class FxApp extends Application {

    private ObservableList<PersonController> all = 
        FXCollections.observableArrayList(PersonController::extract);

    private FilteredList<PersonController> filtered = new FilteredList<>(all);

    private TableView<PersonController> table = new TableView<>();

    private TableColumn<PersonController, String> nameColumn = new TableColumn<>("Name");

    private TableColumn<PersonController, Boolean> checkColumn = new TableColumn<>("Check");

    private Label allLabel = new Label(), filteredLabel = new Label();

    @Override
    public void start(Stage stage) throws Exception {
        // Setup items
        all.add(new PersonController("John Doe"));
        all.add(new PersonController("Jane Doe"));
        // Setup UI
        table.setEditable(true);
        table.getColumns().addAll(Arrays.asList(nameColumn, checkColumn));
        nameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        nameColumn.setCellValueFactory(features -> features.getValue().nameProperty);
        checkColumn.setCellFactory(CheckBoxTableCell.forTableColumn(checkColumn));
        checkColumn.setCellValueFactory(features -> features.getValue().checkProperty);
        allLabel.textProperty().bind(Bindings.size(all).asString("All items: %s"));
        filteredLabel.textProperty().bind(Bindings.size(filtered).asString("Filtered Items: %s"));
        // You may need to add dependencies of your filter here
        filtered.predicateProperty().bind(Bindings.createObjectBinding(this::buildFilter));
        table.setItems(filtered);
        BorderPane pane = new BorderPane();
        pane.setCenter(table);
        pane.setTop(allLabel);
        pane.setBottom(filteredLabel);
        Scene scene = new Scene(pane);
        stage.setScene(scene);
        stage.show();
    }

    private Predicate<PersonController> buildFilter() {
        return person -> person.checkProperty.not().get();
        // OR
        // return person -> person.nameProperty.get().endsWith("Doe");
        // OR
        // some complex filter using other inputs
    }

    private static class PersonController {

        private StringProperty nameProperty = new SimpleStringProperty();

        private BooleanProperty checkProperty = new SimpleBooleanProperty();

        public PersonController(String name) {
            nameProperty.set(name);
        }

        public Observable[] extract() {
            return new Observable[] { nameProperty, checkProperty };
        }

    }

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

}
0 голосов
/ 18 сентября 2018

Итак, вот, наконец, ответ.Спасибо @ James_D за ваше сообщение на здесь

ObservableList<Person> items = table.getItems();

        // initialize counts (only needed once, and only if items is non-empty):
        int vip = 0 ;
        int total = table.getItems().size();
        for (Person item : items) {
            if (Person.Status.VIP.equals(item.getStatus())) vip++ ;
            if (Person.Status.NONVIP.equals(item.getStatus())) nonvip++ ;
        }

        IntegerProperty vipCount = new SimpleIntegerProperty(vip);
        IntegerProperty totalCount = new SimpleIntegerProperty(total);

        totalvip.textProperty().bind(vipCount.asString("VIP: %s"));
        totalperson.textProperty().bind(totalCount.asString("Total persons: %s"));

        items.addListener((
                ListChangeListener.Change<? extends Person> c) -> {
            while (c.next()) {

                if (c.wasAdded()) {
                    for (Person item : c.getAddedSubList()) {
                        totalCount.set(totalCount.get() + 1);
                        if (Person.Status.VIP.equals(item.getStatus())) vipCount.set(vipCount.get() + 1) ;
                    }
                }

                if (c.wasRemoved()) {
                    for (Person item : c.getRemoved()) {
                        totalCount.set(totalCount.get() - 1);
                        item.statusProperty().removeListener(listener);
                        if (Person.Status.VIP.equals(item.getStatus())) vipCount.set(vipCount.get() - 1) ;
                        if(vipCount.get() < 0 ) vipCount.set(0); //prevent negative
                    }
                }

            }
        });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...