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

JavaFX:getController无法更新FXML控制器的跨控制器调用问题

解决JavaFX跨控制器调用方法不更新界面的问题

问题根源

你当前的核心问题有两个:

  1. 在Rem控制器中通过FXMLLoader加载main.fxml得到的Main实例是全新创建的对象,并非界面上正在显示的那个,调用其makeTable方法只会修改新实例的数据,不会影响当前界面的TableView。
  2. Main中的TableView列仅在初始化时加载一次静态columns变量,后续columns更新时,界面不会自动同步列的变化。

推荐解决方案:直接传递当前Main控制器实例给Rem

因为Rem是被Main动态加载到界面中的,所以可以在加载Rem时直接把当前Main的实例传递给Rem控制器,让Rem直接操作界面上的Main实例。

1. 修改Rem.java

添加Main类型的成员变量和setter方法,用于接收当前Main实例:

public class Rem implements Initializable {
    @FXML
    private Button btn;
    private Main mainController;

    @Override
    public void initialize(URL url, ResourceBundle rb) {}    

    // 接收Main控制器实例的setter
    public void setMainController(Main mainController) {
        this.mainController = mainController;
    }

    @FXML
    private void loadTab(ActionEvent event) {
        try{
            var rs = App.getRS("tab2");
            // 调用当前界面上的Main实例的makeTable方法
            mainController.makeTable(rs);
        }catch(Exception ex){
            System.out.println(ex);
        }
    }
}

2. 修改Main.java的loadRem方法

在加载Rem后,将当前Main实例传递给Rem控制器:

@FXML
private void loadRem(ActionEvent event) {
    try{
        // 清空原有Rem组件
        for(int i=remPane.getChildren().size()-1;i>=0;i--){
            remPane.getChildren().remove(i);
        }
        // 加载Rem的FXML
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rem.fxml"));
        Pane panel = fxmlLoader.load();
        // 获取Rem控制器并传递当前Main实例
        Rem remController = fxmlLoader.getController();
        remController.setMainController(this);
        // 添加到界面
        remPane.getChildren().add(panel);
        makeTable(App.getRS("tab1"));
    }catch(Exception ex){
        System.out.println(ex);
    }
}

3. 修正Main中TableView列的绑定逻辑

让TableView的列自动响应静态columns的变化:

public class Main implements Initializable {
    @FXML
    public TableView<ObservableList<String>> Tab;
    @FXML
    private VBox remPane;
    
    private static final ObservableList<TableColumn<ObservableList<String>,String>> columns = FXCollections.observableArrayList();
    private static final javafx.beans.property.ListProperty<ObservableList<String>> rows = new javafx.beans.property.SimpleListProperty();
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // 绑定TableView的数据源到rows
        Tab.itemsProperty().bind(rows);
        // 初始化列,并添加监听:当columns变化时自动更新TableView的列
        Tab.getColumns().setAll(columns);
        columns.addListener((ListChangeListener.Change<? extends TableColumn<ObservableList<String>, String>> change) -> {
            Tab.getColumns().clear();
            Tab.getColumns().addAll(columns);
        });
    }

    // 保留原makeTable和setTable方法不变
    public void makeTable(ResultSet rs){
        try{
            var rsm=rs.getMetaData();
            ObservableList<TableColumn<ObservableList<String>,String>> cols=FXCollections.observableArrayList();
            for(int i=0;i<rsm.getColumnCount();i++){
                final int j=i;
                TableColumn<ObservableList<String>,String> col=new TableColumn(rsm.getColumnName(i+1));
                col.setCellValueFactory(param->new SimpleStringProperty(param.getValue().get(j)));
                cols.add(col);
            }
            ObservableList<ObservableList<String>> arows=FXCollections.observableArrayList();
            while(rs.next()){
                ObservableList<String> row=FXCollections.observableArrayList();
                for(int i=1;i<=rsm.getColumnCount();i++){
                    row.add(rs.getString(i));
                }
                arows.add(row);
            }
            setTable(cols,arows);
        }catch(Exception ex){
            System.out.println(ex);
        }
    }

    private static void setTable(ObservableList<TableColumn<ObservableList<String>,String>> c, ObservableList<ObservableList<String>> r){
        columns.setAll(c);
        rows.set(r);
    }

    // 上面修改后的loadRem方法
    @FXML
    private void loadRem(ActionEvent event) {
        try{
            for(int i=remPane.getChildren().size()-1;i>=0;i--){
                remPane.getChildren().remove(i);
            }
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rem.fxml"));
            Pane panel = fxmlLoader.load();
            Rem remController = fxmlLoader.getController();
            remController.setMainController(this);
            remPane.getChildren().add(panel);
            makeTable(App.getRS("tab1"));
        }catch(Exception ex){
            System.out.println(ex);
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:10:23