This discussion is archived
11 Replies Latest reply: Nov 16, 2012 5:11 PM by 971758 RSS

Closing a window from the controller of that window

971758 Newbie
Currently Being Moderated
In my main controller class I have


public static final Stage fpStage =new Stage();


                    fpStage.setScene(scene);
                    fpStage.show();
okay in my secondary controller class I have
import particlesxml.MainwindowController;


this.okayButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event)  {
              
              MainwindowController.fpStage.hide();
                
                
                
                
            }//end of handle
        }); //end of action event and set on action
        
This compiles just fine but does not work!!!. How do we close window2 brought up by java controller for window1, from java controller for window2.

fpStage for my project is the Stage (window) for Window2.
  • 1. Re: Closing a window from the controller of that window
    971758 Newbie
    Currently Being Moderated
    Making a static method for it in the Main controller and calling it from the secondary controller does not work either.
     public static void fpClose()
        {
            fpStage.hide();
        }
    again it all compiles just fine. No exceptions either. It just doesn't work.
  • 2. Re: Closing a window from the controller of that window
    James_D Guru
    Currently Being Moderated
    This works for me.

    (I'm not advocating this style, BTW; I have no idea what the effect of ignoring the Stage passed into the main application's start(...) method might be; I also really dislike making a Stage available to another class simply by defining it as a public constant.)

    WindowCloseTest.java
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.stage.Stage;
    public class WindowCloseTest extends Application {
      @Override
      public void start(Stage primaryStage) throws Exception {
        FXMLLoader.load(getClass().getResource("WindowCloseTest.fxml"));
      }
      public static void main(String[] args) {
        launch(args);
      }
    }
    WindowCloseTest.fxml
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.BorderPane?>
    <?import javafx.scene.shape.Rectangle?>
    
    <BorderPane xmlns:fx="http://javafx.com/fxml" fx:id="root" fx:controller="WindowCloseTestController">
         <center>
           <Rectangle fill="GREEN" width="200" height="200"/>
         </center>
         <bottom><fx:include source="WindowCloseButtons.fxml" fx:id="windowCloseButtons"/></bottom>
    </BorderPane>
    WindowCloseTestController.java
    import javafx.fxml.FXML;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    import javafx.stage.Window;
    
    public class WindowCloseTestController {
      
      private @FXML Parent root ;
      private @FXML WindowCloseButtonsController windowCloseButtonsController ;
      public static final Stage stage  = new Stage();
      
      public void initialize() {
        stage.setScene(new Scene(root, 400, 200));
        stage.show();
      }
    
    }
    WindowCloseButtons.fxml
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.control.Button?>
    
    <HBox xmlns:fx="http://javafx.com/fxml" fx:controller="WindowCloseButtonsController">
         <Button text="Close" onAction="#close" />
    </HBox>
    WindowCloseButtonsController.java
    public class WindowCloseButtonsController {
      public void close() {
        WindowCloseTestController.stage.hide();
      }
    }
  • 3. Re: Closing a window from the controller of that window
    971758 Newbie
    Currently Being Moderated
    Its very interesting the way you did your second window. It appears that one line brought up a new window.

    <bottom><fx:include source="WindowCloseButtons.fxml" fx:id="windowCloseButtons"/></bottom>


    I did not code fxml I let scenebuilder make it for me. Its about 460 lines of xml like code.
    Anyway I made the second window differently I did it in Javafx like so:

        Scene scene = new Scene(fp);
                        fpStage.setTitle("Fractal Particle");
                        fpStage.setScene(scene);
                        fpStage.show();
    To be perfectly honest with you I do not know a whole lot about the fxml other than it roughly corresponds to equivalent java component placement. As for editing the files directly. I try to avoid it if I can.


    I will try tomorrow to see if I can use your solution.
  • 4. Re: Closing a window from the controller of that window
    James_D Guru
    Currently Being Moderated
    This line
    <bottom><fx:include source="WindowCloseButtons.fxml" fx:id="windowCloseButtons"/></bottom>
    doesn't create a second window: it places the Node defined in WindowCloseButtons.fxml into the bottom of the enclosing BorderPane. In other words, <fx:include source="filename" /> just evaluates to a Node in the same way that a <SomeClass /> tag does (where SomeClass is a subclass of Node). However, if that were placed in a second window, the close button it defines would close the window defined in the WindowTestController class. Again, there are (much) better OO designs than this which would properly encapsulate your classes and avoid excessive coupling between them, but I just wanted to show you your technique should work.

    I actually created the window in the same way you did; it's in the WindowTestController class defined in that post. If you copy and save each of those files, it's a complete executable example.

    I recommend getting somewhat acquainted with FXML; it's not too complex. The tutorial at Oracle http://docs.oracle.com/javafx/2/fxml_get_started/jfxpub-fxml_get_started.htm is a good start, and the reference http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html is fairly short and easy to read.
  • 5. Re: Closing a window from the controller of that window
    James_D Guru
    Currently Being Moderated
    Also, maybe I am interpreting this as being more complex than it really is.

    If the controller is a controller for nodes that are displayed in the window you want to close, it's pretty trivial:

    Example.fxml
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.control.Button ?>
    <HBox xmlns:fx="http://javafx.com/fxml" fx:id="root" fx:controller="ExampleController">
      <Button text="Close" onAction="#close"/>
    </HBox>
    ExampleController.java
    import javafx.fxml.FXML ;
    import javafx.scene.Node ;
    public class ExampleController {
      private @FXML Node root ;
      public void close() {
          root.getScene().getWindow().hide();
      }
    }
    Example.java
    import javafx.application.Application ;
    import javafx.stage.Stage ;
    import javafx.scene.Parent ;
    import javafx.scene.Scene ;
    import javafx.fxml.FXMLLoader ;
    
    public class Example extends Application {
      @Override
      public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("Example.fxml"));
        Scene scene = new Scene(root, 400, 200);
        primaryStage.setScene(scene);
        primaryStage.show();
      }
      public static void main(String[] args) { launch(args); }
    }
    If the controller has no access to nodes that are contained in the window you're closing, then you have to do a bit more work. Of course, you should also ask yourself if that's a good design (from both a UI design point of view and an OO design point of view).
  • 6. Re: Closing a window from the controller of that window
    971758 Newbie
    Currently Being Moderated
    okay I so have this code in my Controller
     this.okayButton.setOnAction(new EventHandler<ActionEvent>() {
    
                @Override
                public void handle(ActionEvent event)  {
                  
                  close();
                    
                    
                }//end of handle
            }); //end of action event and set on action
    
    
      public void close()
        {
            this.root.getScene().getWindow().hide();
        }
    And this code in my fxml file
    <AnchorPane id="AnchorPane" fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="481.0" prefWidth="814.0000999999975" xmlns:fx="http://javafx.com/fxml">
    
    
    <Button fx:id="okayButton" graphicTextGap="4.0" mnemonicParsing="false" prefHeight="55.0" prefWidth="73.0" text="Okay" onAction="#close" >
    But now when I run it does not bring up the second window at all. =(

    Edited by: Alexander B. Java on Nov 9, 2012 7:37 AM
  • 7. Re: Closing a window from the controller of that window
    James_D Guru
    Currently Being Moderated
    First, you're setting the onAction property of the okayButton twice; once in the java code (this.okayButton.setOnAction(...)) and once in the fxml (<Button fx:id="okayButton" ... onAction="#close"/>). You only need one of those.

    What's the scenario here? I'm not sure I fully understand it. Is the okayButton supposed to close the window in which it's displayed, or is it supposed to close some other window?
  • 8. Re: Closing a window from the controller of that window
    971758 Newbie
    Currently Being Moderated
    Its suppose to close the window in which it is displayed.
  • 9. Re: Closing a window from the controller of that window
    971758 Newbie
    Currently Being Moderated
    okay, if the code for closing is in the fxml code for me it will not open window 2 from window 1.

    If the code(shown previously) is only in the controller for window 2. Window 2 opens from window 1 but cannot close via okay button.

    I hope that makes things a little clearer.
  • 10. Re: Closing a window from the controller of that window
    James_D Guru
    Currently Being Moderated
    This sounds pretty confused. Code that opens a window looks like
    Stage stage = ... ;
    ...
    stage.show();
    Code that causes a window to close looks like
    Stage stage = ... ; // get the reference to the stage you want to close
    stage.close();
    You can get the reference to the stage in which a control is displayed with
    Window stage = someControl.getScene().getWindow();
    I suggest you try to create something as simple as possible which has the characteristics you need; a main window containing a button, which when pressed causes a second window to open. The second window should contain a button which, when pressed, causes the same window to close. Once you have that working, you can see if your larger application matches a structure that works. (It's also easier to give assistance if you're working with something small enough that you can post a fully executable example.)
  • 11. Re: Closing a window from the controller of that window
    971758 Newbie
    Currently Being Moderated
    Okay I fixed my problem. I had to write a window manager class with static variables and that was what worked. here is the code.

    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package multiwindwowtest;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    /**
     *
     * @author Workspace
     */
    
    public class WindowManager {
    
        public static Stage stage1 = new Stage();
        public static Stage stage2 = new Stage();
    
        
        public WindowManager() 
        {        
            
     
        }
        
        public void raiseWindow(int type) throws Exception
        {
        if(type==1)
            {
                Parent root = FXMLLoader.load(getClass().getResource("secondwindow.fxml"));
            
            Scene scene = new Scene(root);
            
            stage1.setScene(scene);
            stage1.show();    
                
            }   
            else
            {     
                  Parent root = FXMLLoader.load(getClass().getResource("thirdwindow.fxml"));
            
            Scene scene = new Scene(root);
            
            stage2.setScene(scene);
            stage2.show();    
                
            }
        
        
        }
        public void closeWindow(int type)
        {        
             if(type==1)
            {
        
                stage1.close();
            }
             else
             {
                 stage2.close();
             }
        }
        
    }

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points