【问题标题】:TableView exclude bottom row (total) from sortingTableView 从排序中排除底行(总计)
【发布时间】:2012-03-14 10:17:52
【问题描述】:

我有一个简单的 TableView(Java FX 2.0,但我想这个问题相当普遍),它获得了默认的排序功能。但是表格的最后一行有一个总数,所以我想从排序算法中排除最后一行。

我找到了一个 Swing JTable 的解决方案,它包含在creating a separate table for the total row 中——它可以转置为 TableView,但看起来有点麻烦。我已经尝试实现自己的 Comparator,但我认为不可能创建一个可以同时用于升序和降序的 Comparator。

【问题讨论】:

    标签: java javafx javafx-2 javafx-8


    【解决方案1】:

    使用 JavaFX 8 可以定义排序策略,并且问题更容易解决。假设包含总数的行是TOTAL

    table.sortPolicyProperty().set(t -> {
        Comparator<Row> comparator = (r1, r2) -> 
             r1 == TOTAL ? 1 //TOTAL at the bottom
           : r2 == TOTAL ? -1 //TOTAL at the bottom
           : t.getComparator() == null ? 0 //no column sorted: don't change order
           : t.getComparator().compare(r1, r2); //columns are sorted: sort accordingly
        FXCollections.sort(t.getItems(), comparator);
        return true;
    });
    

    【讨论】:

      【解决方案2】:

      根据 lolsvemir 的回答,我使用自定义比较器成功实现了“TOTAL”。 我使用列的 sortTypeProperty 设置比较器: col.setComparator(new BigDecimalColumnComparator(col.sortTypeProperty()));

      自定义比较器:

      public class BigDecimalColumnComparator implements Comparator<BigDecimal> {
          private final ObjectProperty<TableColumn.SortType> sortTypeProperty;
      
          public BigDecimalColumnComparator(ObjectProperty<TableColumn.SortType> sortTypeProperty) {
              this.sortTypeProperty = sortTypeProperty;
          }
      
          @Override
          public int compare(BigDecimal o1, BigDecimal o2) {
              TableColumn.SortType sortType = sortTypeProperty.get();
              if (sortType == null) {
                  return 0;
              }
      
              if (o1 instanceof TotalBigDecimal) {
                  if (sortType == TableColumn.SortType.ASCENDING) {
                      return 1;
                  } else {
                      return -1;
                  }
              } else if (o2 instanceof TotalBigDecimal) {
                  if (sortType == TableColumn.SortType.ASCENDING) {
                      return -1;
                  } else {
                      return 1;
                  }
              }
      
              return o1.compareTo(o2);
          }
      }
      

      【讨论】:

        【解决方案3】:

        我遇到了同样的问题,并且由于 TableView 属性调用单元格工厂以获取表中可见的尽可能多的行,而不仅仅是针对由 TableView.setItems() 方法设置的列表大小的行索引, IMO最好直接通过单元工厂为需要它的每一列设置汇总值。

        以下是此类单元工厂类的简单示例:

        public class LocalDateTableCell<T> implements 
            Callback<TableColumn<T, LocalDate>, TableCell<T, LocalDate>> {
        
          @Override
          public TableCell<T, LocalDate> call(TableColumn<T, LocalDate> p) {
            TableCell<T, LocalDate> cell = new TableCell<T, LocalDate>() {
              @Override
              protected void updateItem(LocalDate item, boolean empty) {
                super.updateItem(item, empty);
        
                if (item == null || empty) {
                  setText(null);
                } else {
                  setText(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
                    .format(item));
                }
        
                if (getTableView().getItems().size() == getIndex())
                  setText("Test"); // This shows in the summary row
              }
            };
        
            return cell;
          }
        }
        

        这种方法的优点是这样的行根本不参与排序(因为它不在表格项目列表中)并且也不可选择。此外,通过重写 TableRow 工厂可以轻松为整个摘要行设置不同的背景颜色并将其与其他行区分开来。

        但是,向下滚动时,此附加行将不可见,因为 TableView 滚动实现不知道附加行,并且只会滚动到视口底部项目列表中的最后一行。这可以通过覆盖 TableViewSkin.getItemCount() 方法来解决,如下例所示。重写 TableView 本身不是必需的,但如果经常使用此类表,建议这样做。

        public class MyTableViewSkin<T> extends TableViewSkin<T> {
          private TableView<T> tableView;
        
          public MyTableViewSkin(final TableView<T> tableView) {
            super(tableView);
        
            this.tableView = tableView;
          }
        
          @Override
          public int getItemCount() {
            return tableView.getItems() == null || tableView.getItems().size() == 0 ? 
              0 : tableView.getItems().size() + 1;
          }
        }
        
        public class MyTableView<S> extends TableView<S> {
          public MyTableView() {
            super();
        
            setSkin(new MyTableViewSkin<>(this));
          }
        }
        

        这可能看起来像一个 hack,但它就像一个魅力。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多