This filter field will look for each cell in a row and if it finds a match in any of the row, then it retains the row in the TableView else removes it. I have used a TextField as the Filter component (actually, I have used TextFields.createSearchField() from the ControlsFX project. But a simple TextField will work). The filtering logic goes inside the invalidation listener, that is added to the text property of the TextField. I think this is a more cleaner way of implementing the logic, as opposed to implementing the logic in the Key listener (as we do in Swing). Below is the snippet on the filtering logic.
- private void initFilter() {
- txtField = TextFields.createSearchField();
- txtField.setPromptText("Filter");
- txtField.textProperty().addListener(new InvalidationListener() {
- @Override
- public void invalidated(Observable o) {
- if(txtField.textProperty().get().isEmpty()) {
- table.setItems(data);
- return;
- }
- ObservableList<Employee> tableItems = FXCollections.observableArrayList();
- ObservableList<TableColumn<Employee, ?>> cols = table.getColumns();
- for(int i=0; i<data.size(); i++) {
- for(int j=0; j<cols.size(); j++) {
- TableColumn col = cols.get(j);
- String cellValue = col.getCellData(data.get(i)).toString();
- cellValue = cellValue.toLowerCase();
- if(cellValue.contains(txtField.textProperty().get().toLowerCase())) {
- tableItems.add(data.get(i));
- break;
- }
- }
- }
- table.setItems(tableItems);
- }
- });
- }
The whole example is available as a maven project. Download to explore more. This is a very basic implementation. Some of the limitations of this filter is that it calls toString() to compare the contents. That would need some clean up. More features like filtering based on column index, highlighting the matching text in the table, showing some animation in case of really big list of data etc.. can be added to make this a perfect JavaFX control.
Happy coding!!
Table Filter Demo Example : https://drive.google.com/file/d/0B96EBDPI6nZZX2VpdThBa3RnOGc/view?usp=sharing