You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX:如何在同一界面的两个TableView加载同一模型类数据

问题:同一Controller下两个TableView的复用配置方案

我在同一个界面有两个TableView(tableA和tableB),共用同一个Controller,FXML注入代码如下:

@FXML TableView <Product> tableA;
@FXML TableView <Product> tableB;

我想不用重复代码,就能给两个TableView添加相同数据,同时需要初始化所有TableColumn(不确定能不能跳过初始化),初始化代码示例如下:

productName.setCellValueFactory(new PropertyValueFactory<Product, String>("productName"));
    
price.setCellValueFactory(new PropertyValueFactory<Product, Double>("price"));

/* ... */

想请教两个问题:

  1. 有没有通过ID(tableA、tableB)访问数据的解决方案?
  2. 是否必须为每个TableColumn设置ID?

当前Controller代码:

@FXML TableView <Product> tableA;
@FXML TableView <Product> tableB;

@FXML TableColumn <Product, String> productName;
@FXML TableColumn <Product, Double> price;
@FXML TableColumn <Product, Integer> quantity;

ObservableList<Product> tableData;

private void intializeTableColumns() {
    
    tableData = FXCollections.observableArrayList();
    
    productName.setCellValueFactory(new PropertyValueFactory<Product, String>("productName"));
    
    price.setCellValueFactory(new PropertyValueFactory<Product, Double>("price"));

    quantity.setCellValueFactory(new PropertyValueFactory<Product, Integer>("quantity"));
    

}
private void insertInTableData() {
    
    Product product = new Product();
    
    /* ...*/
    
    tableData.addAll(product);
   
    /*Add data in both tables */

    tableA.setItems(tableData);
    tableB.setItems(tableData);       
}

当前FXML代码:

<TableView fx:id="tableA" prefHeight="200.0" styleClass="table-2">
         <columns>
             <TableColumn maxWidth="-Infinity" minWidth="50.0" prefWidth="50.0" text="N°" />
             <TableColumn prefWidth="75.0" text="Product" />
             <TableColumn prefWidth="75.0" text="Price" />
             <TableColumn prefWidth="75.0" text="Quantity" />
         </columns>
         <columnResizePolicy><TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /></columnResizePolicy>
</TableView>
<TableView fx:id="tableB" prefHeight="200.0" styleClass="table-2">
         <columns>
             <TableColumn maxWidth="-Infinity" minWidth="50.0" prefWidth="50.0" text="N°" />
             <TableColumn prefWidth="75.0" text="Product" />
             <TableColumn minWidth="-Infinity" prefWidth="75.0" text="Price" />
             <TableColumn minWidth="-Infinity" prefWidth="75.0" text="Quantity" />
         </columns>
         <columnResizePolicy><TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /></columnResizePolicy>
</TableView>

解决方案

1. 通过ID访问数据的方案

完全可以实现。你可以将两个TableView放入集合,通过循环统一配置,避免重复代码。数据层面,直接共用同一个ObservableList即可(你当前代码已经这么做了,这是最优解——因为ObservableList是双向绑定的,数据变更会自动同步到两个表格,无需额外维护)。

2. 是否必须为每个TableColumn设置ID?

不是必须的。如果想通过FXML将列注入到Controller,才需要给列设置fx:id;如果不想设置ID,可以在Controller中动态创建并配置TableColumn,再添加到对应TableView中,这种方式更灵活,还能避免重复配置。


优化后的代码示例

方案一:动态创建TableColumn(无需修改FXML)

这种方式不用改动现有FXML,直接在Controller中统一配置两个表格的列:

@FXML TableView<Product> tableA;
@FXML TableView<Product> tableB;

ObservableList<Product> tableData;

@Override
public void initialize() {
    // 初始化共用数据集合
    tableData = FXCollections.observableArrayList();
    // 统一配置两个表格
    configureTable(tableA);
    configureTable(tableB);
    // 插入测试数据
    insertInTableData();
}

// 通用表格配置方法
private void configureTable(TableView<Product> tableView) {
    // 创建序号列(非Product属性,需自定义CellFactory)
    TableColumn<Product, Integer> indexColumn = new TableColumn<>("N°");
    indexColumn.setMaxWidth(Double.MAX_VALUE);
    indexColumn.setMinWidth(50.0);
    indexColumn.setPrefWidth(50.0);
    indexColumn.setCellFactory(col -> new TableCell<>() {
        @Override
        protected void updateItem(Integer item, boolean empty) {
            super.updateItem(item, empty);
            setText(empty ? null : String.valueOf(getIndex() + 1));
        }
    });

    // 创建产品名列
    TableColumn<Product, String> productNameCol = new TableColumn<>("Product");
    productNameCol.setPrefWidth(75.0);
    productNameCol.setCellValueFactory(new PropertyValueFactory<>("productName"));

    // 创建价格列
    TableColumn<Product, Double> priceCol = new TableColumn<>("Price");
    priceCol.setPrefWidth(75.0);
    priceCol.setCellValueFactory(new PropertyValueFactory<>("price"));

    // 创建数量列
    TableColumn<Product, Integer> quantityCol = new TableColumn<>("Quantity");
    quantityCol.setPrefWidth(75.0);
    quantityCol.setCellValueFactory(new PropertyValueFactory<>("quantity"));

    // 将列添加到表格
    tableView.getColumns().addAll(indexColumn, productNameCol, priceCol, quantityCol);
    // 设置列调整策略
    tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    // 绑定数据集合
    tableView.setItems(tableData);
}

private void insertInTableData() {
    // 添加测试数据
    tableData.addAll(
        new Product("Product 1", 19.99, 5),
        new Product("Product 2", 29.99, 3)
    );
}

方案二:给FXML列设ID,批量注入配置

如果想保留FXML的列定义,需要给每个表格的列设置唯一fx:id,修改后的FXML如下:

<TableView fx:id="tableA" prefHeight="200.0" styleClass="table-2">
    <columns>
        <TableColumn fx:id="tableAIndex" maxWidth="-Infinity" minWidth="50.0" prefWidth="50.0" text="N°" />
        <TableColumn fx:id="tableAProductName" prefWidth="75.0" text="Product" />
        <TableColumn fx:id="tableAPrice" prefWidth="75.0" text="Price" />
        <TableColumn fx:id="tableAQuantity" prefWidth="75.0" text="Quantity" />
    </columns>
    <columnResizePolicy><TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /></columnResizePolicy>
</TableView>
<TableView fx:id="tableB" prefHeight="200.0" styleClass="table-2">
    <columns>
        <TableColumn fx:id="tableBIndex" maxWidth="-Infinity" minWidth="50.0" prefWidth="50.0" text="N°" />
        <TableColumn fx:id="tableBProductName" prefWidth="75.0" text="Product" />
        <TableColumn fx:id="tableBPrice" minWidth="-Infinity" prefWidth="75.0" text="Price" />
        <TableColumn fx:id="tableBQuantity" minWidth="-Infinity" prefWidth="75.0" text="Quantity" />
    </columns>
    <columnResizePolicy><TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /></columnResizePolicy>
</TableView>

对应的Controller代码:

@FXML TableView<Product> tableA;
@FXML TableView<Product> tableB;

@FXML TableColumn<Product, Integer> tableAIndex;
@FXML TableColumn<Product, String> tableAProductName;
@FXML TableColumn<Product, Double> tableAPrice;
@FXML TableColumn<Product, Integer> tableAQuantity;

@FXML TableColumn<Product, Integer> tableBIndex;
@FXML TableColumn<Product, String> tableBProductName;
@FXML TableColumn<Product, Double> tableBPrice;
@FXML TableColumn<Product, Integer> tableBQuantity;

ObservableList<Product> tableData;

@Override
public void initialize() {
    tableData = FXCollections.observableArrayList();
    // 批量配置两个表格的列
    configureColumns(tableAIndex, tableAProductName, tableAPrice, tableAQuantity);
    configureColumns(tableBIndex, tableBProductName, tableBPrice, tableBQuantity);
    // 绑定数据
    tableA.setItems(tableData);
    tableB.setItems(tableData);
    insertInTableData();
}

private void configureColumns(TableColumn<Product, Integer> indexCol,
                              TableColumn<Product, String> nameCol,
                              TableColumn<Product, Double> priceCol,
                              TableColumn<Product, Integer> quantityCol) {
    // 配置序号列
    indexCol.setCellFactory(col -> new TableCell<>() {
        @Override
        protected void updateItem(Integer item, boolean empty) {
            super.updateItem(item, empty);
            setText(empty ? null : String.valueOf(getIndex() + 1));
        }
    });
    // 配置属性绑定列
    nameCol.setCellValueFactory(new PropertyValueFactory<>("productName"));
    priceCol.setCellValueFactory(new PropertyValueFactory<>("price"));
    quantityCol.setCellValueFactory(new PropertyValueFactory<>("quantity"));
}

private void insertInTableData() {
    tableData.addAll(
        new Product("Product 1", 19.99, 5),
        new Product("Product 2", 29.99, 3)
    );
}

关键说明

  • 两个表格共用同一个ObservableList是最优解,数据变更会自动同步,无需额外维护。
  • 动态创建列的方式更简洁,避免了FXML中大量重复的列定义,也不用维护一堆列的fx:id。
  • 序号列不属于Product的属性,因此需要自定义CellFactory来显示行号,这部分逻辑可以封装复用。

内容的提问来源于stack exchange,提问作者Nacira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:34:51