无法从节点获取JavaFX阶段,因为类com.sun.javafx.stage.EmbeddedWindow无法强制转换为类javafx.stage.Stage

c9x0cxw0  于 2023-01-11  发布在  Java
关注(0)|答案(1)|浏览(168)

我正在尝试关闭当前的fxml以移动到下一个fxml。我遵循了此问题的回复:close fxml window by code, 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的使用上,但是我也找不到解决方案。所以感谢帮助。谢谢!

4dc9hkyq

4dc9hkyq1#

要从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);
    }

    // ...
}

相关问题