通过代码关闭FXML窗口,JavaFX

67

我需要在控制器中通过代码关闭当前的FXML窗口。

我知道在FX中可以使用stage.close()或stage.hide()来实现。

如何在FXML中实现这一点?我尝试过:

private void on_btnClose_clicked(ActionEvent actionEvent) {
        Parent root = FXMLLoader.load(getClass().getResource("currentWindow.fxml"));    
        Scene scene = new Scene(root);

        Stage stage = new Stage();            
        stage.setScene(scene);
        stage.show();
}

但它不起作用!

非常感谢所有的帮助。谢谢!

9个回答

184
  1. 如果您还没有为关闭按钮设置fx:id,请给它添加一个: <Button fx:id="closeButton" onAction="#closeButtonAction">
  2. 在您的控制器类中:

    @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();
    }
    

4
这种方法对我没有用。我收到了一个“NullPointerException”错误。 - Austin
1
太棒了!以防万一,记得检查你的按钮名称(在这个例子中是closeButton)和你的onClick名称(在这个例子中是closeButtonAction)。 - diego matos - keke
1
当我使用这段代码时,出现了以下错误。线程“JavaFX应用程序线程”中的异常java.lang.ClassCastException:com.sun.javafx.stage.EmbeddedWindow无法转换为javafx.stage.Stage。 - ryan.s
3
如果你想关闭应用程序,只需调用Platform.exit()。关闭一个stage(窗口)和关闭应用程序是不同的事情(可以有多个stage)。 - pupeno
这个解决方案非常适合关闭一个次要窗口。closeButton必须是窗口中的一个按钮,用于关闭,而方法closeButtonAction()也必须在同一个类中。 - Orici
显示剩余2条评论

25
如果您有一个扩展了javafx.application.Application;的窗口,您可以使用以下方法。(这将关闭整个应用程序,而不仅仅是窗口。我误解了OP,感谢评论者指出)。
Platform.exit();

例子:

public class MainGUI extends Application {
.........

Button exitButton = new Button("Exit");
exitButton.setOnAction(new ExitButtonListener());
.........

public class ExitButtonListener implements EventHandler<ActionEvent> {

  @Override
  public void handle(ActionEvent arg0) {
    Platform.exit();
  }
}

优化Java 8美学编辑:

 public class MainGUI extends Application {
    .........

    Button exitButton = new Button("Exit");
    exitButton.setOnAction(actionEvent -> Platform.exit());
 }

11
Platform.exit()将关闭所有舞台并关闭整个应用程序。这可能不是期望的行为。 - nonybrighto
4
原帖作者询问如何关闭窗口(舞台),而不是关闭应用程序。 - Bryan Green

12

在接收到被接受方案中的NullPointerException后,我按照以下方式实现了它。

在我的FXML文件中:

<Button onMouseClicked="#onMouseClickedCancelBtn" text="Cancel">

在我的Controller类中:

@FXML public void onMouseClickedCancelBtn(InputEvent e) {
    final Node source = (Node) e.getSource();
    final Stage stage = (Stage) source.getScene().getWindow();
    stage.close();
}

4
如果您不想在控制器中散布链接方法的fxml,可以尝试以下方法:
您需要给它一个“fx:id”,例如“closeButton”。在您的FXML文件中应该像这样:
<Button fx:id="closeButton" layoutX="876.0" layoutY="74.0" mnemonicParsing="false" textAlignment="CENTER">

那么你可以在初始化方法或其他位置编写按钮代码:

然后你只需在initialize方法或者任何你想的地方编写按钮的代码:

@FXML
Button closeButton

public initialize(){
    closeButton.setOnAction(new EventHandler<ActionEvent>(){
        @Override
        public void handle(ActionEvent e){
            ((Stage) closeButton.getScene().getWindow()).close();
        }
    });
}

2

隐藏并不关闭窗口,只是将其置于可见模式。最好的解决方案是:

@FXML
private void exitButtonOnAction(ActionEvent event){
        ((Stage)(((Button)event.getSource()).getScene().getWindow())).close();      
}

1
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
    public void handle(WindowEvent we) {                        
        Platform.setImplicitExit(false);
        stage.close();
    }
});

这相当于“hide”。因此,下次打开时,只需检查“stage”对象是否已退出。如果已退出,则只需调用“show()”,即(stage.show())。否则,您必须启动舞台。

1
我找到了一个不需要触发事件的好方法:
@FXML
private Button cancelButton;

close(new Event(cancelButton, stage, null));

@FXML
private void close(Event event) {
    ((Node)(event.getSource())).getScene().getWindow().hide();                      
}

1

我不确定这是否是最好的方法(或者它是否有效),但你可以尝试一下:

private void on_btnClose_clicked(ActionEvent actionEvent) {

        Window window = getScene().getWindow();   

        if (window instanceof Stage){
            ((Stage) window).close();
        }
}

假设您的控制器是一个节点。否则,您必须先获取该节点(getScene()是Node的一个方法)


1
最终,我找到了一个解决方案。
 Window window =   ((Node)(event.getSource())).getScene().getWindow(); 
            if (window instanceof Stage){
                ((Stage) window).close();
            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接