如何使用JavaFX构建一个具有分页和全局排序的TabbleView——第二部分

第二步:为TableView添加全局排序功能

1. 思路

image.png
  • 由于不能使用内置的排序功能——分页后,内置的排序变成了局部排序,所以我们需要将内置的排序功能关闭,然后使用一个Label组件伪装成表头,设置点击事件,再点击事件中响应全局排序

2. 实现

  1. 准备三张照片——向上的箭头(表示升序排序),向下的箭头(表示降序排序),没有箭头的空白照片(表示没有排序)可以直接截取表格自带的箭头,以假乱真。
  2. 关于全局排序,我们使用Collections提供的排序方法,
java自带的Collections类
    public static  void sort(List list, Comparator c) {
        list.sort(c);
    }

这个排序方法需要传入一个比较器Comparator,这里也有两种方式生成Comparator——匿名函数或Lambda表达式。

  • 使用匿名函数生成升序比较器,即age的排在前面
        Comparator asc = new Comparator() {

            @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 desc = (p1, p2) -> Integer.compare(p2.getAge(), p1.getAge());
  1. 在之前的类TableWithPaginationAndSorting中添加全局排序
    // 使用一个HashMap记录每个Label(表头)的当前排序状态
    private HashMap  orderMap = new HashMap<>();
    public void addGlobalOrdering(TableColumn column,
                                  Comparator ascComparator,
                                  Comparator 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 comparator) {
        Collections.sort(page.getRowDataList(), comparator);
    }
  1. 将我们的新功能加入到测试类中, 只需要添加下面的代码到之前的测试类就好
 // global sorting by column age
        Comparator asc = new Comparator() {

            @Override
            public int compare(People p1, People p2) {
                return Integer.compare(p2.getAge(), p1.getAge());
            }
        };
        Comparator 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

你可能感兴趣的:(如何使用JavaFX构建一个具有分页和全局排序的TabbleView——第二部分)