12

I need a way to close a Stage from within itself by clicking a Button.

I have a main class from which I create the main stage with a scene. I use FXML for that.

public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("Builder.fxml")); stage.setTitle("Ring of Power - Builder"); stage.setScene(new Scene(root)); stage.setMinHeight(600.0); stage.setMinWidth(800.0); stage.setHeight(600); stage.setWidth(800); stage.centerOnScreen(); stage.show(); } 

Now in the main window that appears I have all the control items and menus and stuff, made through FXML and appropriate control class. That's the part where I decided to include the About info in the Help menu. So I have an event going on when the menu Help - About is activated, like this:

@FXML private void menuHelpAbout(ActionEvent event) throws IOException{ Parent root2 = FXMLLoader.load(getClass().getResource("AboutBox.fxml")); Stage aboutBox=new Stage(); aboutBox.setScene(new Scene(root2)); aboutBox.centerOnScreen(); aboutBox.setTitle("About Box"); aboutBox.setResizable(false); aboutBox.initModality(Modality.APPLICATION_MODAL); aboutBox.show(); } 

As seen the About Box window is created via FXML with a controller. I want to add a Button to close the new stage from within the controller.

The only way I found myself to be able to do this, was to define a public static Stage aboutBox; inside the Builder.java class and reference to that one from within the AboutBox.java in method that handles the action event on the closing button. But somehow it doesn't feel exactly clean and right. Is there any better way?

2 Answers 2

27

You can derive the stage to be closed from the event passed to the event handler.

new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent actionEvent) { // take some action ... // close the dialog. Node source = (Node) actionEvent.getSource(); Stage stage = (Stage) source.getScene().getWindow(); stage.close(); } } 
Sign up to request clarification or add additional context in comments.

2 Comments

Close the stage like this bypasses the onCloseRequest event handler (if there is one). I would add the line stage.getOnCloseRequest().handle(null); right before stage.close();
Thank you @beardedlinuxgeek. I had this problem - my window was closing but the event handler I had registered wasn't being called. Your solution fixed the problem.
1

In JavaFX 2.1, you have few choices. The way like in jewelsea's answer or the way what you have done already or modified version of it like

public class AboutBox extends Stage { public AboutBox() throws Exception { initModality(Modality.APPLICATION_MODAL); Button btn = new Button("Close"); btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { close(); } }); // Load content via // EITHER Parent root = FXMLLoader.load(getClass().getResource("AboutPage.fxml")); setScene(new Scene(VBoxBuilder.create().children(root, btn).build())); // OR Scene aboutScene = new Scene(VBoxBuilder.create().children(new Text("About me"), btn).alignment(Pos.CENTER).padding(new Insets(10)).build()); setScene(aboutScene); // If your about page is not so complex. no need FXML so its Controller class too. } } 

with usage like

new AboutBox().show(); 

in menu item action event handler.

5 Comments

Actually have a bit difficulty with the solution. It seems it doesn't like the first version with the FXML.
The problem seems to be fact that you call the class AboutBox.java which itself is supposed to be controll class for the AboutBox.fxml Unless that was the reason why you wrote AboutPage.fxml <
@Meg. Updated the answer. AboutBox.java is not the controller of AboutBox.fxml or AboutPage.fxml either.
So if I get it right, I will end up with 3 files then. AboutBox which is class extending Stage (also containing the creation of the closing button, because it would need to work the way jewelsea wrote - to close the stage from the controller class?). And that AboutBox class will use AboutPage.fxml which uses eg. AboutPage.java to controll it?
@Meg. About jewelsea's answer: you can set that mouse event handler to any button's action and this button will close the stage it belongs to. This button can be in primary stage or in any controller class added to the stage. About my answer: if you have AboutPage.fxml file then yes you will end up with 3 files, otherwise only 1 AboutBox.java file.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.