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

JavaFX跨场景数据传递:点击保存后更新前场景TableView

嘿,这个需求在JavaFX里其实有挺直观的实现方案,我给你分享两种常用的思路,你可以根据自己的项目结构来选:

方法一:使用回调接口(Callback)实现数据传递

这种方式的优势是解耦性好,两个场景的控制器只通过回调接口交互,不会直接依赖彼此。

步骤1:定义Product实体类

首先要创建一个包含所需字段的实体类,并且使用JavaFX的Property类型,这样TableView能自动监听数据变化并更新:

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import java.time.LocalDate;

public class Product {
    private final StringProperty id = new SimpleStringProperty();
    private final StringProperty name = new SimpleStringProperty();
    private final ObjectProperty<LocalDate> date = new SimpleObjectProperty<>();

    // 构造方法
    public Product(String id, String name, LocalDate date) {
        this.id.set(id);
        this.name.set(name);
        this.date.set(date);
    }

    // ID相关的getter、setter和Property方法
    public String getId() { return id.get(); }
    public void setId(String id) { this.id.set(id); }
    public StringProperty idProperty() { return id; }

    // 产品名称相关方法
    public String getName() { return name.get(); }
    public void setName(String name) { this.name.set(name); }
    public StringProperty nameProperty() { return name; }

    // 日期相关方法
    public LocalDate getDate() { return date.get(); }
    public void setDate(LocalDate date) { this.date.set(date); }
    public ObjectProperty<LocalDate> dateProperty() { return date; }
}

步骤2:主场景(带TableView)的控制器实现

在主控制器里初始化TableView,并且在打开表单场景时,传递一个回调函数用于接收新数据:

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.function.Consumer;

public class MainController {
    @FXML
    private TableView<Product> productTable;
    @FXML
    private TableColumn<Product, String> idCol;
    @FXML
    private TableColumn<Product, String> productCol;
    @FXML
    private TableColumn<Product, LocalDate> dateCol;

    private ObservableList<Product> productList = FXCollections.observableArrayList();

    public void initialize() {
        // 绑定表格列与Product的属性
        idCol.setCellValueFactory(cellData -> cellData.getValue().idProperty());
        productCol.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
        dateCol.setCellValueFactory(cellData -> cellData.getValue().dateProperty());
        
        // 给表格设置数据源
        productTable.setItems(productList);
    }

    // 点击"add Product"按钮的事件处理
    @FXML
    private void openAddProductForm(ActionEvent event) throws IOException {
        // 加载表单场景的FXML文件
        FXMLLoader loader = new FXMLLoader(getClass().getResource("add-product-form.fxml"));
        Parent root = loader.load();

        // 获取表单场景的控制器实例
        AddProductController formController = loader.getController();
        
        // 设置回调:当表单点击Save时,将新Product添加到列表
        formController.setOnSaveCallback(newProduct -> {
            productList.add(newProduct);
        });

        // 打开表单窗口
        Stage stage = new Stage();
        stage.setScene(new Scene(root));
        stage.showAndWait(); // 用showAndWait可以阻塞主窗口,直到表单关闭
    }
}

步骤3:表单场景的控制器实现

在表单控制器里定义回调接口,点击Save按钮时触发回调,将数据传回主场景:

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import javafx.scene.Node;
import java.time.LocalDate;
import java.util.function.Consumer;

public class AddProductController {
    @FXML
    private TextField idField;
    @FXML
    private TextField productNameField;
    @FXML
    private DatePicker datePicker;

    private Consumer<Product> onSaveCallback;

    // 设置回调的方法
    public void setOnSaveCallback(Consumer<Product> callback) {
        this.onSaveCallback = callback;
    }

    // Save按钮的事件处理
    @FXML
    private void handleSave(ActionEvent event) {
        // 获取输入框数据并做简单校验
        String id = idField.getText().trim();
        String name = productNameField.getText().trim();
        LocalDate date = datePicker.getValue();

        if (id.isEmpty() || name.isEmpty() || date == null) {
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("输入错误");
            alert.setHeaderText(null);
            alert.setContentText("请填写所有必填字段!");
            alert.showAndWait();
            return;
        }

        // 创建新的Product对象
        Product newProduct = new Product(id, name, date);

        // 触发回调,将数据传回主控制器
        if (onSaveCallback != null) {
            onSaveCallback.accept(newProduct);
        }

        // 关闭表单窗口
        Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        stage.close();
    }
}

方法二:共享ObservableList数据源

如果你的项目中多个场景都需要操作同一组数据,直接共享ObservableList会更直接,TableView会自动监听列表变化并更新。

步骤1:同样定义Product实体类(和方法一完全一致)

步骤2:主场景控制器修改

只需要在打开表单时,把主场景的ObservableList传递给表单控制器:

// 主控制器的openAddProductForm方法修改如下
@FXML
private void openAddProductForm(ActionEvent event) throws IOException {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("add-product-form.fxml"));
    Parent root = loader.load();

    AddProductController formController = loader.getController();
    // 直接传递共享的数据源列表
    formController.setProductList(productList);

    Stage stage = new Stage();
    stage.setScene(new Scene(root));
    stage.showAndWait();
}

步骤3:表单控制器修改

直接操作共享的列表,添加新数据:

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TextField;
import javafx.collections.ObservableList;
import javafx.stage.Stage;
import javafx.scene.Node;
import java.time.LocalDate;

public class AddProductController {
    @FXML
    private TextField idField;
    @FXML
    private TextField productNameField;
    @FXML
    private DatePicker datePicker;

    private ObservableList<Product> productList;

    // 设置共享列表的方法
    public void setProductList(ObservableList<Product> productList) {
        this.productList = productList;
    }

    @FXML
    private void handleSave(ActionEvent event) {
        // 同样的输入校验逻辑
        String id = idField.getText().trim();
        String name = productNameField.getText().trim();
        LocalDate date = datePicker.getValue();

        if (id.isEmpty() || name.isEmpty() || date == null) {
            Alert alert = new Alert(Alert.AlertType.WARNING);
            alert.setTitle("输入错误");
            alert.setHeaderText(null);
            alert.setContentText("请填写所有必填字段!");
            alert.showAndWait();
            return;
        }

        Product newProduct = new Product(id, name, date);
        // 直接添加到共享列表,主场景的TableView会自动更新
        productList.add(newProduct);

        // 关闭窗口
        Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
        stage.close();
    }
}

额外注意事项

  • 确保你的FXML文件中,所有控件都正确设置了fx:id(比如主场景的TableView的fx:id是productTable,表单的TextField是idField等),并且按钮的onAction属性绑定到对应的处理方法。
  • 使用JavaFX的Property类型是关键,这样TableView才能自动响应数据变化,不需要手动调用refresh()方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:15:53