Ajitav Dutta Ajitav Dutta - 2 months ago 89
Java Question

Javafx TableView with multiple filter option

I have written a small application that has a TableView with multiple filter options. It looks like below:

enter image description here

Following are the filter options provided in the application:


  • Object Name/Location -- TextField (Search Table)

  • Release 5/6 Objects -- CheckBox (Release 5 Objects and Release 6 Objects)

  • Live Objects -- CheckBox (Live Objects)



Currently the problem I am facing is that I am only able to use a single filter criteria at time. if I try to use combination of the different filter criteria, it ignores the previous filter criteria and use the last filter criteria to populate the TableView.

e.g. - If I typing the word "OBJ" in the search Table TextField then the table will only contain the rows where the Object name or location contains the word "OBJ". Now if I select the Release 6 Objects Checkbox the table will ignore the "OBJ" filter mentioned in the Search Table TextField and will display all the objects which version is 6.

What I am trying to do is that when I select the Release 6 objects CheckBox, the Table should contain only the rows where the object name/location contains "OBJ" and is having version as 6.

Similarly, I want to use either all the filter criteria or combination of different filter criteria. Can anyone help me with this?

Answer

Finally after multiple attempts, I found a way to achieve this.

Earlier I used local SortedList and FilteredList variable with a ObservableList as Table data. Now I am using a global SortedList and FilteredList variable.

When reading the data from the file, load the data to the FilteredList and then create a new global SortedList using the FilteredList. Then bind the SortedList comparatorProperty with the table comparatorProperty and assign the global SortedList to the table.

Below is the code to do the above

filteredObjects = new FilteredList<>(objects, p -> true);
sortedObjects = new SortedList<>(filteredObjects);
sortedObjects.comparatorProperty().bind(tblPrimeCodeList.comparatorProperty());
tblPrimeCodeList.setItems(sortedObjects);

Then for each filter field add a new ChangeListener, where based on the value of each filter field filter the data will be filtered again. Below is the code for the TextField filter Search Table.

txtFilter.textProperty().addListener((observable, oldValue, newValue) -> {
filteredObjects.setPredicate(obj -> {
    if (!chkRel5.isSelected() && !chkRel6.isSelected()) {
        return false;
    }

    if (newValue == null || newValue.isEmpty()) {
    } else {
        String lowerCaseFilter = newValue.toLowerCase();
        if ( obj.getName().toLowerCase().contains(lowerCaseFilter) ||
             obj.getLocation().toLowerCase().contains(lowerCaseFilter)) {
        } else {
            return false;
        }
    }

    if (chkLiveObj.isSelected() && !obj.getLive()) {
        return false;
    }

    if (!chkRel5.isSelected() && obj.getVersion() == 5) {
        return false;
    }

    if (!chkRel6.isSelected() && obj.getVersion() == 6) {
        return false;
    }

    return true;
  });
});

Below is the code for the CheckBox Release 5 Objects

chkRel5.selectedProperty().addListener(new ChangeListener<Boolean>() {

@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
filteredObjects.setPredicate(obj -> {
    if (!chkRel5.isSelected() && obj.getVersion() == 5) {
        return false;
    }

    if (!chkRel6.isSelected() && obj.getVersion() == 6) {
        return false;
    }

    if (chkLiveObj.isSelected() && !obj.getLive()) {
        return false;
    }

    if (txtFilter.getText().trim().length() > 0) {
        String lowerCaseFilter = txtFilter.getText().trim().toLowerCase();
        if ( obj.getName().toLowerCase().contains(lowerCaseFilter) ||
             obj.getLocation().toLowerCase().contains(lowerCaseFilter)) {
        } else {
            return false;
        }
    }
    return true;
  });
    sortedObjects = new SortedList<>(filteredObjects);
  }
});