我需要使表格始终按特定列排序(当启用某些设置时).例如,当用户按他想要的列对表进行排序时,程序将自动添加另一列进行排序.

这是我的代码-程序必须始终按ID ASC排序:

public class JavaFxTest7 extends Application {

    private static record Student(int id, String name, int mark) {};

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        var table = this.createTable();
        table.getSortOrder().addListener((ListChangeListener<? super TableColumn<Student, ?>>)(change) -> {
            //if some settings enabled then
            var idColumn = table.getColumns().get(0);
            if (!table.getSortOrder().contains(idColumn)) {
                idColumn.setSortType(TableColumn.SortType.ASCENDING);
                table.getSortOrder().add(0, idColumn);
            }
        });
        var scene = new Scene(table, 300, 200);
        stage.setScene(scene);
        stage.show();
    }

    private TableView<Student> createTable() {
        var table = new TableView<Student>();
        table.getItems().addAll(new Student(1, "Billy", 3),
                new Student(2, "Johnny", 4), new Student(3, "Mickey", 5));
        var idColumn = new TableColumn<Student, Integer>("ID");
        idColumn.setCellValueFactory((data) ->  new ReadOnlyObjectWrapper<>(data.getValue().id()));
        var nameColumn = new TableColumn<Student, String>("Name");
        nameColumn.setCellValueFactory((data) ->  new ReadOnlyStringWrapper(data.getValue().name()));
        var markColumn = new TableColumn<Student, Integer>("Mark");
        markColumn.setCellValueFactory((data) ->  new ReadOnlyObjectWrapper<>(data.getValue().mark()));
        table.getColumns().addAll(idColumn, nameColumn, markColumn);
        table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);
        return table;
    }
}

这就是结果:

enter image description here

按ID排序始终按计划添加.问题是,使用我的解决方案,不可能删除按其他列排序-无论您点击name列多少次,name列始终存在于sortOrder列表中.

有人能告诉我如何修复它吗?

推荐答案

您看到的行为似乎是设计的.如果用户点击列without shift down,那么用户正在请求表reset排序顺序,以便它仅由所点击的列组成.因此,您单击"Name"列,希望将其从排序顺序中删除,但实际上您请求从排序顺序中删除all other列.然后,因为您的听众立即重新添加了"ID"列,所以看起来好像出了问题.

也就是说,如果您考虑到监听器中的上述行为,那么实现您想要的内容似乎是可能的(至少在RDX 22中是这样).这是一个例子.然而,请注意,由于(必要)使用runLater,当更改排序顺序时,列标题的内容有时会闪烁.

package com.example;

import java.util.ArrayList;
import java.util.List;
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.SortType;
import javafx.scene.control.TableView;

public class PrefixedSortOrder<S> {

  /**
   * Makes it so the {@link TableView#getSortOrder() sortOrder} of {@code table} always contains the
   * columns of {@code prefixCols}, in order, as a prefix. This constraint is maintained whether the
   * {@code sortOrder} is changed programmatically or via user interaction.
   *
   * @param <S> The item type of the {@code table}.
   * @param table the {@code TableView}
   * @param prefixCols the columns to always have at the start of the {@code sortOrder}
   */
  public static <S> void install(TableView<S> table, List<TableColumn<S, ?>> prefixCols) {
    var pso = new PrefixedSortOrder<>(table, prefixCols);
    table.getSortOrder().addListener(pso::onChanged);
  }

  private final ObservableList<TableColumn<S, ?>> sortOrder;
  private final List<TableColumn<S, ?>> prevSortOrder;
  private final List<TableColumn<S, ?>> prefixCols;
  private boolean fixingSortOrder;

  private PrefixedSortOrder(TableView<S> table, List<TableColumn<S, ?>> prefixCols) {
    this.sortOrder = table.getSortOrder();
    this.prevSortOrder = new ArrayList<>(sortOrder);
    this.prefixCols = List.copyOf(prefixCols);
  }

  private void onChanged(ListChangeListener.Change<? extends TableColumn<S, ?>> c) {
    if (fixingSortOrder) return;

    if (isPrefixMissing()) {
      // Sort order changed in manner consistent with a simple click.
      fixingSortOrder = true;
      // Avoid modifying the list from within the listener.
      Platform.runLater(
          () -> {
            fixSortOrder();
            cacheSortOrder();
            fixingSortOrder = false;
          });
    } else {
      // Sort order changed in manner consistent with a shift+click.
      cacheSortOrder();
    }
  }

  private boolean isPrefixMissing() {
    if (sortOrder.size() < prefixCols.size()) {
      return true;
    }

    for (int i = 0; i < prefixCols.size(); i++) {
      if (prefixCols.get(i) != sortOrder.get(i)) {
        return true;
      }
    }
    return false;
  }

  private void fixSortOrder() {
    if (sortOrder.size() == 1) {
      // Sort order changed via user interaction (probably).
      var column = sortOrder.get(0);
      if (prefixCols.contains(column)) {
        // User toggled sort direction of prefix column.
        sortOrder.setAll(prevSortOrder);
      } else if (wasSortOrderCleared(column)) {
        // User removed non-prefix column from sort order.
        sortOrder.setAll(prefixCols);
      } else {
        // User toggled sort direction of non-prefix column.
        sortOrder.addAll(0, prefixCols);
      }
    } else {
      // Sort order changed programmatically (probably).
      var temp = new ArrayList<>(sortOrder);
      temp.removeAll(prefixCols);
      temp.addAll(0, prefixCols);
      sortOrder.setAll(temp);
    }
  }

  private boolean wasSortOrderCleared(TableColumn<S, ?> column) {
    return column.getSortType() == SortType.ASCENDING && prevSortOrder.contains(column);
  }

  private void cacheSortOrder() {
    prevSortOrder.clear();
    prevSortOrder.addAll(sortOrder);
  }
}

Java相关问答推荐

Java应用程序崩溃时试图读取联系人从电话

Java WireMock定义存根在Cucumber并行执行的多线程测试中失败

Java 8中的多个字段和计数

在Spring终结点中,是否可以同时以大写和小写形式指定枚举常量?

解释左移在Java中的工作原理

对字符串长度进行排序,但颠倒了顺序(最长字符串在前)

在向WebSphere中的文档添加元素时iText挂起

由于在生成器模式中使用泛型,lambda表达式中的返回类型错误

Groovy/Java:匹配带引号的命令选项

Instancio未在日志(log)中显示测试失败消息

来自外部模块的方面(对于Java+Gradle项目)不起作用

为什么StandardOpenOption.CREATE不能通过Ubuntu在中小企业上运行?

从泛型枚举创建EnumMap

有没有办法知道在合并中执行了什么操作?

使IntelliJ在导入时优先 Select 一个类或将另一个标记为错误

用于Java的Visual Studio代码完成不起作用

如何使用Java ZoneID的区域设置?

Java CDI:@Singleton@Startup@Inject无法实现接口

控制器建议异常处理

ExecutorService:如果我向Executor提交了太多任务,会发生什么?