TableView列顺序变更时change.wasPermutated()始终返回false如何解决?
解决JavaFX两个TableView列顺序同步问题
问题原因
JavaFX中拖动TableView列调整顺序时,内部并非通过列表排列(permutation)实现,而是先移除目标列,再将其插入到新位置。因此ListChangeListener的change.wasPermutated()始终返回false,触发的是remove和add类型的变更事件。
解决方案
我们可以直接监听第一个表格的列列表变更,根据其列的顺序,重新排列第二个表格的对应列。由于两个表格的列是独立实例,可通过列标题(或自定义标识)匹配对应列,再同步顺序。
修改后的完整代码
import javafx.application.Application; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyStringWrapper; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.scene.Scene; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class JavaFxTest7 extends Application { private static class Student { private int id; private String name; private int mark; public Student(int id, String name, int mark) { this.id = id; this.name = name; this.mark = mark; } public int getId() { return id; } public String getName() { return name; } public int getMark() { return mark; } } public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { var table1 = createTable(); var table2 = createTable(); // 监听table1的列顺序变更,同步到table2 table1.getColumns().addListener((ListChangeListener<? super TableColumn<Student, ?>>) change -> { // 获取table1当前的列标题顺序 List<String> columnOrder = table1.getColumns().stream() .map(TableColumn::getText) .collect(Collectors.toList()); // 按照该顺序重新排列table2的列 List<TableColumn<Student, ?>> newColumnList = new ArrayList<>(); for (String colTitle : columnOrder) { for (TableColumn<Student, ?> col : table2.getColumns()) { if (col.getText().equals(colTitle)) { newColumnList.add(col); break; } } } // 更新table2的列顺序 table2.getColumns().setAll(newColumnList); }); var scene = new Scene(new VBox(table1, table2), 300, 300); stage.setScene(scene); stage.show(); } private TableView<Student> createTable() { var table = new TableView<>(FXCollections.observableList(Arrays.asList( 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().getId())); var nameColumn = new TableColumn<Student, String>("Name"); nameColumn.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().getName())); var markColumn = new TableColumn<Student, Integer>("Mark"); markColumn.setCellValueFactory(data -> new ReadOnlyObjectWrapper<>(data.getValue().getMark())); table.getColumns().addAll(idColumn, nameColumn, markColumn); table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN); return table; } }
代码说明
- 监听
table1.getColumns()的变更事件,每次变更时获取table1当前的列标题顺序。 - 根据标题匹配
table2中的对应列,生成新的列顺序列表。 - 通过
table2.getColumns().setAll(newColumnList)更新table2的列顺序,确保与table1完全一致。
这种方式无需区分具体的变更类型(remove/add/permutate),无论通过何种方式修改table1的列顺序,都能可靠同步到table2。
内容的提问来源于stack exchange,提问作者user5182503
相关产品推荐
相关产品推荐

