Reputation: 1398
My TableView populates data from database. When user clicks a column header, it sort the data based on it. This feature is out of the box. However, I have too many records to populate them at a time. Say I have 1000 records and the table only shows 500. When I sort it based on a column, it only shorts the 500 already populated record.
I'd like to override the sorting behaviour so when user clicks a column header, it will reload the data from database and provide necessary information for "order by" clause in the query. My problem is, I don't know
Upvotes: 6
Views: 4080
Reputation: 484
I know it is a bit late but I just got to the same issue. Since I did not find solution online I did some digging and figured out that it is best to override sort() method. If you try to create EventHandler for OnSort, it will be fired after rows has been already sorted and refreshed. Since you probably want to directly show the results from database, it is best to ignore sorting of local data altogether.
So to do it properly just create some class that extends TableView. Then override sort method as below. To do some custom logic, just implement SortListener and set it through a setter. I hope it helps someone even after so many years.
public class OurTableView<S> extends TableView<S> {
private SortListener sortListener;
@Override
public void sort() {
if (sortListener!=null) {
sortListener.sort();
} else {
super.sort();
}
}
public void setSortListener(SortListener sortListener) {
this.sortListener = sortListener;
}
public interface SortListener {
void sort();
}
}
Upvotes: 0
Reputation: 1398
I got an ugly solution that only solves a half of the problem. I can attach a listener to column header click event, but can't remove default TableView sorting behaviour.
private void initTable() {
...
...
//listen to sorting type (ASC/DESC) change
SortTypeChangeListener sortTypeChangeListener = new SortTypeChangeListener();
clmName.sortTypeProperty().addListener(sortTypeChangeListener);
clmGender.sortTypeProperty().addListener(sortTypeChangeListener);
reload();
//listen to sortorder change
tblMember.getSortOrder().addListener(new ListChangeListener<TableColumn<VOMember, ?>>() {
@Override
public void onChanged(Change<? extends TableColumn<VOMember, ?>> change) {
reload();
}
});
}
private void reload() {
/**
* Get sorted columns and sorting versus (ASC/DESC)
*/
List<String> lstSortedColumn = new ArrayList<String>();
List<String> lstSortedType = new ArrayList<String>();
for (TableColumn<VOMember, ?> tc : tblMember.getSortOrder()) {
PropertyValueFactory valFactory = (PropertyValueFactory) tc.getCellValueFactory();
valFactory.getProperty();
lstSortedColumn.add(valFactory.getProperty());
lstSortedType.add(tc.getSortType().name());
}
/**
* Retrieve data from database. Pass the sorting information
*/
List<VOMember> lstMember = controller.retrieve(lstSortedColumn, lstSortedType);
ObservableList<VOMember> data = FXCollections.observableList(lstMember);
tblMember.setItems(data);
}
class SortTypeChangeListener implements InvalidationListener {
@Override
public void invalidated(Observable o) {
/**
* If the column is not in sortOrder list, just ignore.
* It avoids intermittent duplicate reload() calling
*/
TableColumn col = (TableColumn) ((SimpleObjectProperty) o).getBean();
if (!tblMember.getSortOrder().contains(col)) {
return;
}
reload();
}
}
I'd like to hear your view/comment on this.
Upvotes: 2