Issue
I have a tableview and possibility to search by single column, e.g.
Problem starts when I have a lot of columns and there has to be a lot of text fields for each column. Is there easy way to make something like first row in the tableview is row of editable search boxes?
Solution
If you need a row of text fields, one per column, you may want to place a HBox container above the TableView and put TextField instances into the HBox. In order to get the sizing right, you may bind the text field (preferred!) widths to the respective column widths, and the HBox (preferred!) width to the TableView widht:
hbox.prefWidthProperty().bind(tableview.widthProperty());
textfield1.prefWidthProperty().bind(col1.widthProperty());
textfield2.prefWidthProperty().bind(col2.widthProperty());
A quite simple but effective approach for the filtering would be to wrap the TableView data in a FilteredList and update the filter predicate if the text within one of the search boxes changes:
ObservableList<Person> data = FXCollections.observableArrayList();
data.add(....); // add data ...
// wrap the data collection in a filterd list:
filteredList = new FilteredList<>(data);
filteredList.setPredicate(p -> true); // Initial: show all rows
// set the FilteredList as TableView data:
tableview.itemsProperty().set(filteredList);
// Create a changelistener for the search box:
// "dataObject" is an instance of your data class/entity etc.
textfield1.textProperty().addListener((observable, oldValue, newValue) -> {
updatePredicate();
});
textfield2.textProperty().addListener((observable, oldValue, newValue) -> {
updatePredicate();
});
If your columns do not fit in the TabelView's viewport, then you might want to place the search boxes in the column header, i.e., set the TextFields as graphic property to the TableColumn:
col1.setGraphic(textfield1);
col2.setGraphic(textfield2);
At first, the graphic node will hide the column title. You may try to correct this via css styling (just a hint, I'd need to check this out), or you pack a new Label together with the textfield in a HBox that will be the column header graphic node.
Method for updating the filter predicate:
private void updatePredicate() {
filteredList.setPredicate((data) -> {
boolean showItem = true;
if (!textfield1.getText().isEmpty()) {
showItem = showItem && (data.getField1().contains(textfield1.getText()));
}
if (!textfield2.getText().isEmpty()) {
showItem = showItem && (data.getField2().contains(textfield2.getText()));
}
return showItem;
});
}
Hope that helps :-)
Answered By - Robert Rohm
Answer Checked By - Timothy Miller (JavaFixing Admin)