之前有讲过,最近在开发一个以 JavaFX
为技术栈的桌面端项目。之前解决了表格数据刷新的问题:JavaFX使用MapValueFactory渲染表格数据时的数据刷新问题。最近又碰到一个问题:需要为指定的行加载子表格。
在 StackOverFlow
上找到了一个 Demo
: JavaFX SubTable Demo。渲染效果如下:

直接将代码拷贝到现有项目中,关键代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| tableView.setRowFactory(tv -> new TableRow<Map<String, Object>>() { Node detailsPane; { this.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> { if ("JavaFX Application Thread".equals(Thread.currentThread().getName())) { if (isNowSelected) { Map<String, Object> selectedItem = tv.getSelectionModel().getSelectedItem(); List<Map<String, Object>> subTableItems = childSensorMap.get(selectedItem.get("sensor_code").toString()); if (CollectionUtils.isNotEmpty(subTableItems)) { detailsPane = constructSubTable(FXCollections.observableArrayList(subTableItems)); this.getChildren().add(detailsPane); } } else { if (detailsPane != null) { this.getChildren().remove(detailsPane); detailsPane = null; } } } }); } @Override protected double computePrefHeight(double width) { if (isSelected() && detailsPane != null) { return super.computePrefHeight(width) + detailsPane.prefHeight(60); } else { return super.computePrefHeight(width); } }
@Override protected void layoutChildren() { super.layoutChildren(); if (isSelected() && detailsPane != null) { double width = getWidth(); double paneHeight = detailsPane.prefHeight(width); detailsPane.resizeRelocate(0, getHeight() - paneHeight, width, paneHeight); } } });
|
Web
端实现的子表格是有首行缩进效果,这里也遵循原样式,子表格的样式代码如下:
1 2 3 4 5 6 7
| subTable.getColumns().addAll(list); subTable.setItems(items);
subTable.setPrefHeight(60 + (items.size() * 47));
subTable.setPadding(new Insets(0, 0, 0, 50)); subTable.setStyle("-fx-border-color: #42bff4;");
|
最终实现效果如下:

参考文档
Javafx Tables inside row table
JavaFX SubTable Demo