2017-02-09 9 views
0

В настоящее время я пытаюсь отфильтровать данные в моем TableView с использованием FilteredList с predicate. У меня есть 2 ComboBoxes для фильтрации значений.Фильтрация JFX TableView с несколькими значениями

Мой стол содержит Result. Каждый Result имеет Student, что Student имеет номер Classroom, в который он входит. Это значения, которые я хочу отфильтровать.

У меня нет проблем при фильтрации данных, используя только 1 ComboBox. Однако я не знаю, как отфильтровать его на основе обоих одновременно. Единственное реальное решение, которое я мог бы придумать, - это много if операторов как в changeListeners на каждом ComboBox, и это похоже на нерегулярно сложный способ сделать это.

Значения в моем TableView отображаются несколько раз, если я использую следующий код.

private void filterData(){ 
     ObservableList<Result> observableList = FXCollections.observableList(view.getResultTableView().getAllResultsList()); 
     FilteredList<Result> filteredData = new FilteredList<>(observableList, p -> true); 

     view.getClassroomComboBox().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { 

      filteredData.setPredicate(result -> { 

       if (newValue.equals(view.getAllClassroomsChoice()) || newValue.equals(result.getStudent().getClassroom())) { 
        return true; 
       } 
       else 
        return false; 
      }); 

      if(newValue.equals(view.getAllClassroomsChoice())){ 
       view.getStudentComboBox().setAllStudents(); 
      } 
      else{ 
       view.getStudentComboBox().setStudentsByClassroom((Classroom) newValue); 
      } 
     }); 

     view.getStudentComboBox().getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { 
      filteredData.setPredicate(result -> { 

       if (newValue.equals(view.getAllClassroomsChoice()) || newValue.equals(result.getStudent())) { 
        return true; 
       } 
       else 
        return false; 
      }); 
     }); 


     SortedList<Result> sortedData = new SortedList<>(filteredData); 

     sortedData.comparatorProperty().bind(view.getResultTableView().comparatorProperty()); 

     view.getResultTableView().setItems(sortedData); 

    } 

ответ

2

Во-первых, не воссоздавайте структуру данных каждый раз. Просто обновите предикат на FilteredList.

Вы можете создать предикаты для каждого поля со списком и привязать их к значению в поле со списком. Затем вы можете комбинировать предикаты с помощью Predicate.and(...) и привязать свойство предиката отфильтрованного списка к результату.

Вот подобный пример:

import java.util.Arrays; 
import java.util.List; 
import java.util.function.Function; 
import java.util.function.Predicate; 

import javafx.application.Application; 
import javafx.beans.binding.Bindings; 
import javafx.beans.property.ObjectProperty; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.FXCollections; 
import javafx.collections.transformation.FilteredList; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 

public class MultipleFilterTableExample extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     TableView<Person> table = new TableView<>(); 
     table.getColumns().add(column("Name", Person::nameProperty)); 
     table.getColumns().add(column("Email", Person::emailProperty)); 
     table.getColumns().add(column("Gender", Person::genderProperty)); 

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

     TextField nameFilterField = new TextField(); 

     ObjectProperty<Predicate<Person>> nameFilter = new SimpleObjectProperty<>(); 
     ObjectProperty<Predicate<Person>> genderFilter = 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())); 

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

     filteredItems.predicateProperty().bind(Bindings.createObjectBinding(
       () -> nameFilter.get().and(genderFilter.get()), 
       nameFilter, genderFilter)); 

     Button clear = new Button("Clear Filters"); 
     clear.setOnAction(e -> { 
      genderFilterCombo.setValue(null); 
      nameFilterField.clear(); 
     }); 

     HBox filters = new HBox(5, nameFilterField, genderFilterCombo, clear); 
     filters.setPadding(new Insets(5)); 
     BorderPane root = new BorderPane(table, filters, null, null, null); 
     Scene scene = new Scene(root, 600, 600); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private List<Person> createData() { 
     return Arrays.asList(
       new Person("Jacob Smith", "[email protected]", Person.Gender.MALE), 
       new Person("Isabella Johnson", "[email protected]", Person.Gender.FEMALE), 
       new Person("Ethan Williams", "[email protected]", Person.Gender.MALE), 
       new Person("Emma Jones", "[email protected]", Person.Gender.FEMALE), 
       new Person("Michael Brown", "[email protected]", Person.Gender.MALE) 
     ); 
    } 

    private 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 { 

     public enum Gender {MALE, FEMALE } 

     private final StringProperty name = new SimpleStringProperty(); 
     private final StringProperty email = new SimpleStringProperty() ; 
     private final ObjectProperty<Gender> gender = new SimpleObjectProperty<>(); 

     public Person(String name, String email, Gender gender) { 
      setName(name); 
      setEmail(email); 
      setGender(gender); 
     } 

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

Большое спасибо, это работает безупречно. –

 Смежные вопросы

  • Нет связанных вопросов^_^