24

I made a JavaFX project and created the GUI for the first-login frame in the java Scene Builder. When the login is successful, the login frame must be closed and the next frame must be visible (main program frame). I can make the new frame appear, but I can't make the login frame closed. I tried stuff like dispose() but nothing works. Below is the code for the main class:

public class KuberComm extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);
        stage.setResizable(false);
        stage.setTitle("Login to KuberComm");
        stage.setScene(scene);

        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

The handler for the login button is located in another class (controller class made by the NetBeans IDE). I can't figure out what the frame's name is in order to use it in the controller class.

Any help will be much appreciated!

Johan Kaving
  • 4,870
  • 1
  • 27
  • 21
Aristomenis
  • 401
  • 2
  • 4
  • 10
  • Maybe this answer is useful. check it out. [close fxml window by controller](https://stackoverflow.com/questions/13567019/close-fxml-window-by-code-javafx) – H. Najafi Sep 06 '17 at 16:53

5 Answers5

45

give your button a name in the controller class:

@FXML
public Button closeButton;

and add this method:

@FXML
public void handleCloseButtonAction(ActionEvent event) {
    Stage stage = (Stage) closeButton.getScene().getWindow();
    stage.close();
}

In your FXML you need a reference to the button name and the method to call onAction:

<Button fx:id="closeButton" cancelButton="true" layoutX="350.0" layoutY="767.0" mnemonicParsing="false" onAction="#handleCloseButtonAction" prefWidth="100.0" text="Close" />

This would close the stage that this button is on.

Moh-Aw
  • 2,976
  • 2
  • 30
  • 44
  • If I use this method, `Platform.runLater()` won't run any `Runnable` coming from this specific controller anymore. Don't ask me why. – m0skit0 May 26 '16 at 11:47
11

Similar to the other answers but more precise.

@FXML
public void handleCloseButtonAction(ActionEvent event) {
    ((Stage)(((Button)event.getSource()).getScene().getWindow())).close();
}
SedJ601
  • 12,173
  • 3
  • 41
  • 59
8

Use

stage.hide()

If you do this from a controller, you can get the stage from any Node inside the scene of the stage (if necessary let the FXML loader assign one to a field of the controller using the id attribute from the fxml namespace in the fxml):

Window stage = node.getScene().getWindow();
fabian
  • 80,457
  • 12
  • 86
  • 114
  • 1
    stage.close() is equivalent to Window.hide() according to the documentation https://docs.oracle.com/javase/8/javafx/api/javafx/stage/Stage.html#close-- – kervin Feb 12 '16 at 00:16
  • 1
    @kervin So what??? Both close the stage, but using `hide()` doesn't require a cast, if the stage is accessed using the last code snippet. This is exactly what the OP asked, isn't it??? – fabian Feb 12 '16 at 00:25
6

Thanks for your time to reply,but in the end I found out how to fix it. I used

((Node)(event.getSource())).getScene().getWindow().hide();

in the if that it's responsible for the successful login. I mean, after a dialog appears that informs the user about their successful login, that code goes there.

(I imported the right stuff too in order to make that line of code work)

fabian
  • 80,457
  • 12
  • 86
  • 114
Aristomenis
  • 401
  • 2
  • 4
  • 10
0

Although

    getScene().getWindow();

on a Node will get you the stage from the controller, it's important to note that calling close() or hide() are equivalent, and will simply make the login window invisible. As for using dispose():

This link might help to clear up any confusion.

Forager
  • 307
  • 2
  • 10