javafx TableView 如何冻结第一列
时间: 2024-02-02 09:02:57 浏览: 140
table 冻结列
JavaFX TableView 冻结第一列可以通过以下方式实现:
1. 在 TableView 中添加一个新的 TableColumn,用于显示第一列的数据,同时设置它的宽度为固定值,禁止调整列宽。
```java
TableColumn<Person, String> firstColumn = new TableColumn<>("First");
firstColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
firstColumn.setMinWidth(100);
firstColumn.setMaxWidth(100);
firstColumn.setResizable(false);
```
2. 将原先的第一列从 TableView 中移除,并将它的数据和样式设置到新添加的 TableColumn 上。
```java
TableColumn<Person, String> nameColumn = tableview.getColumns().remove(0);
firstColumn.setCellFactory(nameColumn.getCellFactory());
firstColumn.setStyle(nameColumn.getStyle());
firstColumn.setEditable(nameColumn.isEditable());
firstColumn.setSortable(nameColumn.isSortable());
firstColumn.setContextMenu(nameColumn.getContextMenu());
firstColumn.setSortType(nameColumn.getSortType());
firstColumn.setComparator(nameColumn.getComparator());
firstColumn.setGraphic(nameColumn.getGraphic());
```
3. 将新添加的 TableColumn 和原先的第一列插入到 TableView 的列列表中,使得新添加的 TableColumn 在第一列位置。
```java
tableview.getColumns().add(0, firstColumn);
tableview.getColumns().add(1, nameColumn);
```
4. 在 new TableView() 时,需要使用一个 Callback 来实现 TableView 的滚动同步。
```java
Callback<TableView<Person>, TableViewSkin<Person>> callback = new Callback<TableView<Person>, TableViewSkin<Person>>() {
@Override
public TableViewSkin<Person> call(TableView<Person> tableView) {
return new FrozenTableViewSkin<>(tableView);
}
};
TableView<Person> tableview = new TableView<>(data);
tableview.setSkin(callback.call(tableview));
```
其中,FrozenTableViewSkin 是一个自定义的 TableViewSkin,用于实现 TableView 的滚动同步。代码实现如下:
```java
public class FrozenTableViewSkin<T> extends TableViewSkin<T> {
private final TableView<T> frozenTable;
private final Group frozenGroup;
private final ScrollBar frozenScrollBar;
public FrozenTableViewSkin(TableView<T> tableView) {
super(tableView);
frozenTable = new TableView<>();
frozenTable.getSelectionModel().setSelectionMode(tableView.getSelectionModel().getSelectionMode());
frozenTable.setItems(tableView.getItems());
frozenTable.getColumns().addAll(tableView.getColumns().subList(0, 1));
frozenTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
frozenGroup = new Group(frozenTable);
frozenScrollBar = new ScrollBar();
frozenScrollBar.setOrientation(Orientation.VERTICAL);
frozenScrollBar.setMin(0);
frozenScrollBar.setMax(1);
frozenScrollBar.setVisibleAmount(1);
frozenScrollBar.valueProperty().bindBidirectional(tableView.verticalScrollBarProperty().valueProperty());
frozenScrollBar.visibleProperty().bindBidirectional(tableView.verticalScrollBarProperty().visibleProperty());
frozenScrollBar.managedProperty().bindBidirectional(tableView.verticalScrollBarProperty().managedProperty());
getChildren().addAll(frozenGroup, frozenScrollBar);
registerChangeListener(tableView.widthProperty(), tableView.heightProperty(), tableView.visibleProperty(), layoutBoundsProperty(), tableView.verticalScrollBarProperty());
layoutChildren();
}
@Override
protected void layoutChildren(double x, double y, double w, double h) {
super.layoutChildren(x, y, w, h);
double frozenWidth = frozenTable.getColumns().stream().mapToDouble(TableColumnBase::getWidth).sum();
double frozenHeight = Math.max(frozenTable.getHeight(), frozenTable.getItems().size() * frozenTable.getFixedCellSize());
frozenTable.resize(frozenWidth, frozenHeight);
frozenGroup.setLayoutX(getTableHeaderRow().getBoundsInParent().getWidth());
frozenGroup.setLayoutY(getTableHeaderRow().getBoundsInParent().getHeight());
frozenScrollBar.resizeRelocate(frozenTable.getBoundsInParent().getMaxX(), frozenTable.getBoundsInParent().getMinY(), frozenScrollBar.getWidth(), frozenTable.getBoundsInParent().getHeight());
}
}
```
通过以上方式,即可实现 JavaFX TableView 的冻结第一列功能。
阅读全文