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

Swing嵌入JavaFX后EmbeddedWindow转Stage失败,求FXML窗口关闭方案

问题根源

你遇到的ClassCastException是因为嵌入在JFXPanel中的JavaFX场景,其所属窗口并非独立的javafx.stage.Stage,而是com.sun.javafx.stage.EmbeddedWindow——这是JavaFX为Swing嵌入场景专门生成的内部窗口类型,强行转Stage自然会报错。

解决方案

根据你的需求,提供两种直接可行的处理方式:

方式一:直接操作上层Swing窗口(推荐)

因为JavaFX界面是依附于Swing窗口(JFrame/JDialog)存在的,关闭对应的Swing窗口就能达到关闭当前嵌入界面的效果,同时可以启动下一个界面。

步骤:

  1. 在FXML控制器中添加Swing窗口的引用:
public class YourFXMLController {
    private JFrame parentSwingFrame;

    // 提供设置父窗口的方法
    public void setParentSwingFrame(JFrame parentFrame) {
        this.parentSwingFrame = parentFrame;
    }

    // 关闭按钮的事件处理方法
    @FXML
    private void onCloseButtonClicked(ActionEvent event) {
        // 关闭当前Swing窗口
        parentSwingFrame.dispose();
        
        // 在这里启动下一个界面(可以是新的Swing窗口,或者新的JFXPanel嵌入界面)
        launchNextInterface();
    }

    private void launchNextInterface() {
        // 示例:打开新的Swing窗口
        JFrame nextFrame = new JFrame("下一个界面");
        nextFrame.setSize(800, 600);
        nextFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        nextFrame.setVisible(true);
    }
}
  1. 在初始化JFXPanel的Swing代码中,传递窗口引用给控制器:
public class SwingMain {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame mainFrame = new JFrame("嵌入JavaFX的界面");
            JFXPanel fxPanel = new JFXPanel();
            mainFrame.add(fxPanel);

            // 加载FXML并获取控制器
            try {
                FXMLLoader loader = new FXMLLoader(SwingMain.class.getResource("your.fxml"));
                Parent root = loader.load();
                YourFXMLController controller = loader.getController();
                // 传递Swing窗口引用
                controller.setParentSwingFrame(mainFrame);

                fxPanel.setScene(new Scene(root));
                mainFrame.setSize(800, 600);
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                mainFrame.setVisible(true);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}

方式二:替换JFXPanel中的场景(无需关闭窗口)

如果不需要关闭整个Swing窗口,只是切换FXML内容,可以直接替换JFXPanel的Scene,避免窗口关闭再打开的开销:

@FXML
private void switchToNextScene(ActionEvent event) {
    // 从事件源获取当前场景,再拿到EmbeddedWindow,最后获取对应的JFXPanel
    Node sourceNode = (Node) event.getSource();
    Scene currentScene = sourceNode.getScene();
    EmbeddedWindow embeddedWindow = (EmbeddedWindow) currentScene.getWindow();
    JFXPanel fxPanel = (JFXPanel) embeddedWindow.getHost();

    // 加载下一个FXML并替换场景
    try {
        Parent nextRoot = FXMLLoader.load(getClass().getResource("next.fxml"));
        fxPanel.setScene(new Scene(nextRoot));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

内容的提问来源于stack exchange,提问作者Minh Long Vu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:55:10