提问者:小点点

无法从Node获取JavaFx阶段,因为类com. sun.javafx.阶段.EmbeddedWindow无法转换为类javafx.阶段.阶段


我正在尝试关闭当前fxml以移动到下一个。我按照这个问题的回答:通过代码关闭fxml窗口,javafx:

@FXML private javafx.scene.control.Button closeButton;

@FXML
private void closeButtonAction(){
    // get a handle to the stage
    Stage stage = (Stage) closeButton.getScene().getWindow();
    // do what you have to do
    stage.close();
}

我遇到了与下面未回答的评论相同的问题:

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: com.sun.javafx.stage.EmbeddedWindow cannot be cast to javafx.stage.Stage

所有其他答案也无济于事。EmbeddedWindow上几乎没有讨论,所以我不知道下一步该做什么。上一个屏幕是用javax. swing制作的,而不是JavaFx,过渡如下:

import javafx.embed.swing.JFXPanel;

// more code

        JFXPanel fxPanel = new JFXPanel();
        this.add(fxPanel);
        
        this.setTitle("Title");
        this.setSize(1024, 768);
        this.setVisible(true);
        Platform.runLater(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    FXMLLoader loader = new FXMLLoader(getClass().getResource("<String url to my fxml file>"));
                    ScreenController controller = new ScreenController();
                    loader.setController(controller);
                    Parent root = loader.load();
                    fxPanel.setScene(new Scene(root));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

// more code

当我写完上下文时,我认为问题可能在于JFXPanel的使用,但我也找不到解决方案。所以感谢帮助。谢谢!


共1个答案

匿名用户

要从JavaFX控制器关闭混合Swing和JavaFX应用程序中包含的JFrame,您需要向控制器提供足够的信息来关闭窗口。正确解耦的最佳方法可能是在控制器中设置一个知道如何关闭窗口的Runnable

public class ScreenController {

    private Runnable windowCloser ;

    public void setWindowCloser(Runnable windowCloser) {
        this.windowCloser = windowCloser;
    }

    // ...

    @FXML
    private void closeButtonAction(){
        
        // do what you have to do

        // close the current window:
        windowCloser.run();
    }

    // ...
}

然后:

    JFXPanel fxPanel = new JFXPanel();
    this.add(fxPanel);
    
    this.setTitle("Title");
    this.setSize(1024, 768);
    this.setVisible(true);

    // Assuming this is a JFrame subclass
    // (otherwise replace "this" with a reference to the JFrame):

    Runnable windowCloser = () -> SwingUtilities.invokeLater(
        () -> this.setVisible(false)
    );

    Platform.runLater(() -> {

        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("<String url to my fxml file>"));
            ScreenController controller = new ScreenController();

            controller.setWindowCloser(windowCloser);

            loader.setController(controller);
            Parent root = loader.load();
            fxPanel.setScene(new Scene(root));
        } catch (IOException e) {
            e.printStackTrace();
        }
    });

您还应该考虑将FXML加载到当前的JFXPanel中,这要容易得多:

public class ScreenController {


    // ...

    @FXML
    private Button closeButton;

    @FXML
    private void closeButtonAction(){

        Parent root = /* load next FXML */ ;
        closeButton.getScene().setRoot(root);
    }

    // ...
}