JavaFX中TableView单元格合并实现方法技术求助
实现JavaFX TableView单元格合并的完整方案
看起来你已经搭好了单元格合并的基础框架,接下来咱们一步步把功能补全,实现你想要的合并效果。
首先,你已经定义了核心的CellSpanTableView、CellSpan、SpanModel类,这些是实现合并的核心支撑,接下来需要完善几个关键环节:
1. 自定义合并单元格渲染类
咱们需要创建一个SpanTableCell来处理单元格的跨度显示与隐藏逻辑,替换默认的表格单元格:
import javafx.scene.control.TableCell; public class SpanTableCell<S, T> extends TableCell<S, T> { @Override protected void updateItem(T item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setStyle(""); setVisible(true); setManaged(true); return; } setText(item.toString()); CellSpanTableView<S> tableView = (CellSpanTableView<S>) getTableView(); SpanModel spanModel = tableView.getSpanModel(); if (spanModel != null && spanModel.isCellSpanEnabled()) { int rowIndex = getIndex(); int columnIndex = getTableColumn().getIndex(); CellSpan currentSpan = spanModel.getCellSpanAt(rowIndex, columnIndex); // 检查当前单元格是否是被合并的子单元格 boolean isMergedChild = false; for (int i = rowIndex - 1; i >= 0; i--) { CellSpan prevSpan = spanModel.getCellSpanAt(i, columnIndex); if (prevSpan != null && rowIndex < i + prevSpan.getRowSpan()) { isMergedChild = true; break; } } if (isMergedChild) { // 隐藏被合并的单元格 setVisible(false); setManaged(false); } else { setVisible(true); setManaged(true); // 设置合并单元格的样式 if (currentSpan != null) { setStyle(String.format( "-fx-border-width: 1; -fx-border-color: black; " + "-fx-padding: 5px;" )); } else { setStyle("-fx-border-width: 1; -fx-border-color: black; -fx-padding: 5px;"); } } } } }
2. 关联自定义单元格到表格列
在buildBasicTableView方法中,把原来的单元格工厂替换为咱们的SpanTableCell,示例如下:
// 修改Column Sections的单元格工厂 columnSections.setCellFactory(column -> new SpanTableCell<>()); // 同理替换其他列的单元格工厂 columnItems.setCellFactory(column -> new SpanTableCell<>()); columnLevels.setCellFactory(column -> new SpanTableCell<>());
3. 完善样式表cell-span.css
确保你的样式表包含合并单元格的边框优化规则,避免重复边框:
.cell-span-table-view { -fx-border-color: black; } .cell-span-table-view .table-cell { -fx-alignment: center-left; -fx-border-color: black; -fx-border-width: 1px; } /* 合并单元格的底部边框隐藏,避免与下方单元格重复 */ .cell-span-table-view .table-cell:visible { -fx-background-color: white; }
4. 调整SpanModel的合并规则
你当前的SpanModel只实现了特定列的简单合并规则,可根据需求扩展,比如支持多列、不同行数的合并:
tableView.setSpanModel(new SpanModel() { private final CellSpan spanTwoRows = new CellSpan(2, 1); private final CellSpan spanThreeRows = new CellSpan(3, 1); @Override public CellSpan getCellSpanAt(int rowIndex, int columnIndex) { // 第0列:每4行合并3行 if (columnIndex == 0 && rowIndex % 4 == 0) { return spanThreeRows; } // 第1列:每3行合并2行 else if (columnIndex == 1 && rowIndex % 3 == 0) { return spanTwoRows; } // 其他情况不合并 return null; } @Override public boolean isCellSpanEnabled() { return true; } });
5. 补全不完整的编辑逻辑
你提供的buildBasicTableView代码末尾不完整,这里补全columnLevels的编辑事件:
columnLevels.setOnEditCommit( new EventHandler<TableColumn.CellEditEvent<Row, String>>() { @Override public void handle(TableColumn.CellEditEvent<Row, String> event) { ((Row) event.getTableView().getItems().get(event.getTablePosition().getRow())) .setLevel(event.getNewValue()); } });
同时要确保你的Row类正确实现了对应属性的getter/setter方法(比如getSection()、setSection()),保证PropertyValueFactory能正确绑定数据。
测试验证
整合所有代码后运行项目,就能看到单元格按照你定义的规则合并的效果了。当表格滚动、数据更新时,SpanTableCell的updateItem方法会自动触发,维护合并单元格的显示状态。
内容的提问来源于stack exchange,提问作者user9787264
相关产品推荐
相关产品推荐

