2015-10-08 61 views
2

我寫了一個小例子:的JavaFX - 多個文本框應該過濾一個實現代碼如下

import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.collections.transformation.FilteredList; 
import javafx.scene.Scene; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.TextField; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 

public class MultipleFilterTextfields extends Application { 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     VBox vbox = new VBox(); 

     TextField firstNameFilterTextField = new TextField(); 
     TextField lastNameFilterTextField = new TextField(); 

     TableView<Person> tableView = new TableView<>(); 

     ObservableList<Person> list = FXCollections.observableArrayList(new Person("Peter", "Schmidt"), 
       new Person("Hans-Peter", "Schmidt"), new Person("Hans", "Mustermann")); 
     FilteredList<Person> filterList = new FilteredList<>(list); 
     tableView.setItems(filterList); 

     TableColumn<Person, String> firstNameCol = new TableColumn<>("FirstName"); 
     TableColumn<Person, String> lastNameCol = new TableColumn<>("LastName"); 
     firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName")); 
     lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName")); 

     firstNameFilterTextField.textProperty().addListener((obsVal, oldValue, newValue) -> { 
      filterList.setPredicate(person -> person.getFirstName().contains(newValue)); 
     }); 
     lastNameFilterTextField.textProperty().addListener((obsVal, oldValue, newValue) -> { 
      filterList.setPredicate(person -> person.getLastName().contains(newValue)); 
     }); 

     tableView.getColumns().addAll(firstNameCol, lastNameCol); 

     vbox.getChildren().addAll(firstNameFilterTextField, lastNameFilterTextField, tableView); 

     Scene scene = new Scene(vbox, 250, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public class Person { 

     private String firstName; 
     private String lastName; 

     public Person(String firstName, String lastName) { 
      super(); 
      this.firstName = firstName; 
      this.lastName = lastName; 
     } 

     public String getFirstName() { 
      return firstName; 
     } 

     public String getLastName() { 
      return lastName; 
     } 
    } 

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

它看起來像這樣:

enter image description here

上方tableView有兩個TextField S,一個過濾firstName,另一個過濾lastName。如果我在第一個字段中輸入:「Hans」,表格會過濾出兩個人「Hans-Peter Schmidt」和「Hans Mustermann」。如果我在第二個中輸入「Schmidt」,它將過濾「Peter Schmidt」和「Hans-Peter Schmidt」。

問題是,我無法同時對firstNamelastName進行過濾(使用上面的代碼)。

你有什麼想法嗎?

感謝您的幫助!

回答

1

如何

filteredList.predicateProperty().bind(Bindings.createObjectBinding(() -> 
    person -> person.getFirstName().contains(firstNameFilterTextField.getText()) 
      && person.getLastName().contains(lastNameFilterTextField.getText()), 

    firstNameFilterTextField.textProperty(), 
    lastNameFilterTextField.textProperty() 

)); 

而不是在文本字段的兩個監聽器。

Bindings.createObjectBinding(...)需要一個函數來生成計算值,以及綁定必須遵守的任何屬性的列表。在這種情況下,如果任何一個文本字段發生更改,我們都要重新計算,所以屬性列表就是兩個文本字段的文本屬性。

函數必須返回一個謂詞,所以它的格式爲() -> predicate。 謂詞本身就是映射Personboolean的函數,因此斷言看起來像person -> condition,並且第一個參數的整體形式是

() -> person -> condition 

注意你仍然可以用兩個監聽器做到這一點:

firstNameFilterTextField.textProperty().addListener((obsVal, oldValue, newValue) -> { 
     filterList.setPredicate(person -> person.getFirstName().contains(firstNameFilterTextField.getText()) 
      && person.getLastName().contains(lastNameFilterTextField.getText())); 
    }); 
    lastNameFilterTextField.textProperty().addListener((obsVal, oldValue, newValue) -> { 
     filterList.setPredicate(person -> person.getFirstName().contains(firstNameFilterTextField.getText()) 
      && person.getLastName().contains(lastNameFilterTextField.getText())); 
    }); 

但單綁定似乎更優雅(對我來說)。

相關問題