第二步:为TableView添加全局排序功能
1. 思路
image.png- 由于不能使用内置的排序功能——分页后,内置的排序变成了局部排序,所以我们需要将内置的排序功能关闭,然后使用一个Label组件伪装成表头,设置点击事件,再点击事件中响应全局排序
2. 实现
- 准备三张照片——向上的箭头(表示升序排序),向下的箭头(表示降序排序),没有箭头的空白照片(表示没有排序)可以直接截取表格自带的箭头,以假乱真。
- 关于全局排序,我们使用
Collections
提供的排序方法,
java自带的Collections类
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
这个排序方法需要传入一个比较器Comparator
,这里也有两种方式生成Comparator
——匿名函数或Lambda表达式。
- 使用匿名函数生成升序比较器,即age小的排在前面
Comparator<People> asc = new Comparator<People>() {
@Override
public int compare(People p1, People p2) {
return Integer.compare(p1.getAge(), p2.getAge());
}
};
这里没有去写if-else if-else
去排序,而是使用静态方法Integer.compare()
去排序,它等价于
if(p2.getAge() > p1.getAge()){
return 1;
}else if(p2.getAge() = p1.getAge()){
return 0;
}else{
return -1
}
Integer.compare()方法体源码
- 使用Lambda生成降序比较器,即age大的排在前面
Comparator<People> desc = (p1, p2) -> Integer.compare(p2.getAge(), p1.getAge());
- 在之前的类
TableWithPaginationAndSorting
中添加全局排序
// 使用一个HashMap记录每个Label(表头)的当前排序状态
private HashMap<Label, String> orderMap = new HashMap<>();
public void addGlobalOrdering(TableColumn<T, ?> column,
Comparator<? super T> ascComparator,
Comparator<? super T> descComparator) {
/** label setting **/
// set column name to label text
Label label = new Label(column.getText());
label.setMinWidth(column.getMinWidth());
label.setMaxWidth(column.getMaxWidth());
label.setPrefWidth(column.getPrefWidth());
// 初始化时默认没有排序
orderMap.put(label, "NO");
/** column setting **/
// set built-in column name to null
column.setText(null);
// turn off built-in order in TableView
column.setSortable(false);
// make label replace original table header
column.setGraphic(label);
ImageView ascImg = new ImageView("/image-app/asc.png");
ImageView descImg = new ImageView("/image-app/desc.png");
ImageView noImg = new ImageView("/image-app/no.png");
// set event
label.setOnMouseClicked(mouseEvent -> {
// sort only one column every time, so make other columns unsorted
orderMap.keySet().stream().forEach(lab -> lab.setGraphic(noImg));
switch (orderMap.get(label)) {
case "NO":
orderMap.replace(label, "ASC");
label.setGraphic(ascImg);
order(ascComparator);
updatePagination();
break;
case "ASC":
orderMap.put(label, "DESC");
label.setGraphic(descImg);
order(descComparator);
updatePagination();
break;
case "DESC":
orderMap.put(label, "ASC");
label.setGraphic(ascImg);
order(ascComparator);
updatePagination();
break;
}
});
}
/**
* sort a list by given comparator
* @param comparator
*/
private void order(Comparator<? super T> comparator) {
Collections.sort(page.getRowDataList(), comparator);
}
- 将我们的新功能加入到测试类中, 只需要添加下面的代码到之前的测试类就好
// global sorting by column age
Comparator<People> asc = new Comparator<People>() {
@Override
public int compare(People p1, People p2) {
return Integer.compare(p2.getAge(), p1.getAge());
}
};
Comparator<People> desc = (p1, p2) -> Integer.compare(p2.getAge(), p1.getAge());
// order by column age
table.addGlobalOrdering(peopleTable.getColumns().get(1),
asc,
desc);
完整示例见:https://github.com/lhuangjs/blog/tree/master/src/main/java/javafx/tableview
网友评论