【问题标题】:JavaFx: bind columns reorderingJavaFx:绑定列重新排序
【发布时间】:2018-02-12 18:34:22
【问题描述】:

我有一个视图,在那个视图中有几个 tableViews,但假设我有两个表。当我重新排序第一个表中的列时(通过使用拖放),我想在第二个表中做同样的事情。我在尝试某种方式,但我得到了 IllegalStateException: Duplicate TreeTableColumns detected in TreeTableView columns list with titles ''

这是我试过的:

    private void handleDragAndDrop() {
        firstTable.getColumns().addListener((ListChangeListener<? super TableColumn<?, ?>>) c -> {
            while (c.next()) {
                List<String> addedIDs = c.getAddedSubList()
                        .stream()
                        .map(TableColumn::getId)
                        .collect(Collectors.toList());
                Map<String, String> changedIds = getChangedIds(addedIDs);
                changedIds.entrySet()
                        .stream()
                        .reduce((firstEntry, lastEntry) -> lastEntry)
                        .ifPresent(entry-> reorderTheSecondTable(secondTable.getColumns(),entry.getValue(),
                                entry.getKey()));
            }
        });
    }

    private Map<String, String> getChangedIds(List<String> iDs) {
        return new LinkedHashMap<>(iDs.stream()
                .skip(1) // I don't need the first column, that will be never reordered.
                .filter(id -> !id.equals(String.valueOf(iDs.indexOf(id)))) // I need only the changed id-index pairs.
                .collect(Collectors.toMap(i -> String.valueOf(iDs.indexOf(i)), Function.identity())));
    }

    private void reorderTheSecondTable(ObservableList<? extends TableColumnBase<?, ?>> list, String start, String end) {
        Collections.rotate(list.subList(Integer.valueOf(start), Integer.valueOf(end) + 1), 1);
    }

列的 id 从 1table.getColumns().size()-1(0 是不可变列)

异常在Collections.rotate(...行抛出

我不知道这是否是正确的做法,但我没有找到更好的解决方案,甚至这也不是解决方案,因为它不起作用。

【问题讨论】:

  • 两个 TableView 是否映射同一个对象?
  • 没有第一个表有TableView&lt;FirstTablesData&gt; firstTable,第二个表是TreeTableView&lt;SecondTableData&gt; secondTable
  • 两个 TableView 中的列数是否相同?
  • 是的,列的数量始终相同,或者更准确地说,每个表的列数都相同。

标签: java javafx javafx-8 bind tablecolumn


【解决方案1】:

你可以这样做:

TableView<FirstTablesData> firstTable = new TableView<>();

// create a list that holds the original order of the columns:
List<TableColumn<FirstTablesData, ?>> firstTableOriginalColumns = new ArrayList<>(...);

firstTable.getColumns().setAll(firstTableOriginalColumns);

// same for second table:

TableView<SecondTablesData> secondTable = new TableView<>();
List<TableColumn<SecondTablesData, ?>> secondTableOriginalColumns = new ArrayList<>(...);
secondTable.getColumns().setAll(secondTableOriginalColumns);

firstTable.getColumns().addListener((Change<? extends TableColumn<FirstTablesData,?>> change) -> 
    secondTable.getColumns().setAll(firstTable.getColumns().stream()
        .mapToInt(firstTableOriginalColumns::indexOf)
        .mapToObj(secondTableOriginalColumns::get)
        .collect(Collectors.toList())));

这会创建“记住”每个表中列的原始顺序的列表。侦听器只是在第一个表的原始列列表中查找索引,并为第二个表的列创建一个与该排序相对应的列表。此代码假定两个表的列数相同。

这是一个 SSCCE:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javafx.application.Application;
import javafx.collections.ListChangeListener.Change;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class CoordinatedTableColumns extends Application {

    @Override
    public void start(Stage primaryStage) {
        TableView<Object> firstTable = new TableView<>();
        List<TableColumn<Object, ?>> firstTableOriginalColumns = Arrays.asList(
                new TableColumn<>("Column 1"),
                new TableColumn<>("Column 2")
        );
        firstTable.getColumns().setAll(firstTableOriginalColumns);

        TableView<String> secondTable = new TableView<>();
        List<TableColumn<String, ?>> secondTableOriginalColumns = Arrays.asList(
                new TableColumn<>("Column A"),
                new TableColumn<>("Column B")
        );
        secondTable.getColumns().setAll(secondTableOriginalColumns);

        firstTable.getColumns().addListener((Change<? extends TableColumn<Object,?>> change) -> 
        secondTable.getColumns().setAll(firstTable.getColumns().stream()
            .mapToInt(firstTableOriginalColumns::indexOf)
            .mapToObj(secondTableOriginalColumns::get)
            .collect(Collectors.toList())));

        HBox root = new HBox(5, firstTable, secondTable);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

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

【讨论】:

  • 一切正常,非常感谢。
  • 我想知道是否可以通过仅删除修改后的列并以正确的顺序添加它们来优化它...因为如果我有 30(或更多)列包含数据并且我只是交换2 列彼此相邻,然后我删除了 28 并添加了 28 不必要的,对吗?
  • @Sunflame 但是你为什么要关心这个?最小化更改的代码将非常复杂且难以维护。
  • 我只是在考虑是否可以减少不必要的操作,因为是否有一个视图中最多有 50 列和 5 个表的情况,所以如果我只重新排序其中的 2 个后台有很多工作。
  • @Sunflame 再说一遍,你为什么在乎?您是否确定存在性能问题?如果没有,您应该努力编写最简单和最可维护的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-05
  • 1970-01-01
  • 2018-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多