2017-02-09 6 views
0

Ich versuche derzeit, Daten in meinem TableView mit FilteredList mit predicate zu filtern. Ich habe 2 ComboBoxes, um die Werte zu filtern.Filtern von JFX TableView mit mehreren Werten

Meine Tabelle enthält Result. Jede Result hat eine Student, dass Student eine Classroom hat er in gehört. Das sind die Werte, die ich möchte, dass sie durch filtern.

Ich habe keine Probleme, wenn ich Daten nur mit 1 ComboBox filtern. Allerdings weiß ich nicht, wie man beides gleichzeitig filtert. Die einzige wirkliche Lösung, die ich mir vorstellen könnte, wäre eine Menge von if Aussagen in beiden changeListeners auf jedem ComboBox und das scheint wie unnötig komplizierte Art und Weise, es zu tun.

Die Werte in meinem TableView werden mehrfach angezeigt, wenn ich den folgenden Code verwende.

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

    } 

Antwort

2

Erstens, erstellen Sie die Datenstruktur nicht jedes Mal neu. Aktualisieren Sie einfach das Prädikat auf FilteredList.

Sie können für jedes Kombinationsfeld Prädikate erstellen und jedes an den Wert im Kombinationsfeld binden. Dann können Sie Prädikate mit Predicate.and(...) kombinieren und die Prädikateigenschaft der gefilterten Liste an das Ergebnis binden.

Hier ist ein ähnliches Beispiel:

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

Vielen Dank, es funktioniert einwandfrei. –