JavaFx:绑定列重新排序
JavaFx: bind columns reordering
我有一个视图,在那个视图中有几个 table 视图,但假设我有两个 table。当我对第一个 table 中的列重新排序时(通过使用拖放),我想在第二个 table 中做同样的事情。我在某种程度上尝试过,但我明白了
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 从 1
到 table.getColumns().size()-1
(0 是 immutable 列)
在第 Collections.rotate(...
行抛出异常
我不知道这是否是正确的方法,但我没有找到任何更好的解决方案,甚至这也不是解决方案,因为它不起作用。
你可以这样做:
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())));
这将创建 "remember" 每个 table 中列的原始排序的列表。侦听器只是在原始列列表中查找第一个 table 的索引,并为第二个 table 的列创建一个与该排序相对应的列表。此代码假定两个 table 具有相同的列数。
这是一个 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);
}
}
我有一个视图,在那个视图中有几个 table 视图,但假设我有两个 table。当我对第一个 table 中的列重新排序时(通过使用拖放),我想在第二个 table 中做同样的事情。我在某种程度上尝试过,但我明白了
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 从 1
到 table.getColumns().size()-1
(0 是 immutable 列)
在第 Collections.rotate(...
我不知道这是否是正确的方法,但我没有找到任何更好的解决方案,甚至这也不是解决方案,因为它不起作用。
你可以这样做:
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())));
这将创建 "remember" 每个 table 中列的原始排序的列表。侦听器只是在原始列列表中查找第一个 table 的索引,并为第二个 table 的列创建一个与该排序相对应的列表。此代码假定两个 table 具有相同的列数。
这是一个 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);
}
}