Switching scene in javaFX

2019-03-28 00:14发布

I have problem when trying to close current scene and open up another scene when menuItem is selected. My main stage is coded as below:

public void start(Stage primaryStage) throws Exception {
   primaryStage.setTitle("Shop Management");
   Pane myPane = (Pane)FXMLLoader.load(getClass().getResource
("createProduct.fxml"));
   Scene myScene = new Scene(myPane);        
   primaryStage.setScene(myScene);
   primaryStage.show();
}

Then within createProduct.fxml, when menuItem is onclick, it will perform this:

public void gotoCreateCategory(ActionEvent event) throws IOException {
    Stage stage = new Stage();
    stage.setTitle("Shop Management");
    Pane myPane = null;
    myPane = FXMLLoader.load(getClass().getResource("createCategory.fxml"));
    Scene scene = new Scene(myPane);
    stage.setScene(scene);
    stage.show();
}

It does opened up createCategory.fxml. However, the previous panel which is createProduct.fxml does not close. I know there's something called stage.close() to do this but I have no idea where to implement it since I not passing the scene from main right from the start. I wonder how should I fix this.

Thanks in advance.

3条回答
别忘想泡老子
2楼-- · 2019-03-28 00:51

You have multiple ways to solve your problem, few of them I tell you. What I understood from your question is that you want to create an application which contains a navigation (menu bar) on the top and by using it user can switch to any screen.

The easiest method is to make your Navigation Bar available globally, either by you make it static or by passing it to screens, or by any other method. Second, make a single screen (say Border Pane) and load other screens on it (its center).

You can also use spring integration in project so that it provide you better injection of controllers. See Ref : http://www.zenjava.com/2011/10/25/views-within-views-controllers-within-controllers/

You can also create your own single screen controller and manage other screens using that. See Ref: https://blogs.oracle.com/acaicedo/entry/managing_multiple_screens_in_javafx1

But for this (above) you have to change or update your current architecture.

查看更多
再贱就再见
3楼-- · 2019-03-28 00:52

you can get the current open window/stage from the fx:id . just make sure you have an item in your createProduct.fxml that has fx:id like below

<TextField fx:id="username" labelFloat="true" layoutX="80.0" layoutY="300.0" prefHeight="32.0" prefWidth="260.0" promptText="Login Username" />

Hope you see the fx:id attribute.

Then in your start controller, leave as it is

    public void start(Stage primaryStage) throws Exception {
   primaryStage.setTitle("Shop Management");
   Pane myPane = (Pane)FXMLLoader.load(getClass().getResource("createProduct.fxml"));
   Scene myScene = new Scene(myPane);        
   primaryStage.setScene(myScene);
   primaryStage.show();
}

Then in your CreateProductController.java

//make sure you import the javafx item you have used, eg have used TextField
import javafx.scene.control.TextField;

    public class CreateProductController implements Initializable {
// make sure the variable has the same type as the item in the fxml "TextField" and same name "username"
    @FXML
    private TextField username;
//we use the above variable since its referencing the window to which it belongs because of the fx:id attribute, then we close it
    private void closeStage() 
    {
      ((Stage) username.getScene().getWindow()).close();
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
    }

    public void gotoCreateCategory(ActionEvent event) throws IOException {
       closeStage();// we close the old stage
       Stage stage = new Stage();
       stage.setTitle("Shop Management");
       Pane myPane = null;
       myPane = FXMLLoader.load(getClass().getResource("createCategory.fxml"));
       Scene scene = new Scene(myPane);
       stage.setScene(scene);    
       stage.show();
    }
}
查看更多
Ridiculous、
4楼-- · 2019-03-28 01:14

You have to make some changes in start method, like..

public void start(Stage primaryStage) throws Exception {
   primaryStage.setTitle("Shop Management");

   FXMLLoader myLoader = new FXMLLoader(getClass().getResource("createProduct.fxml"));

   Pane myPane = (Pane)myLoader.load();

   CreateProductController controller = (CreateProductController) myLoader.getController();

   controller.setPrevStage(primaryStage);

   Scene myScene = new Scene(myPane);        
   primaryStage.setScene(myScene);
   primaryStage.show();
}

and your CreateProductController.java will be,

public class CreateProductController implements Initializable {

    Stage prevStage;

    public void setPrevStage(Stage stage){
         this.prevStage = stage;
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
    }

    public void gotoCreateCategory(ActionEvent event) throws IOException {
       Stage stage = new Stage();
       stage.setTitle("Shop Management");
       Pane myPane = null;
       myPane = FXMLLoader.load(getClass().getResource("createCategory.fxml"));
       Scene scene = new Scene(myPane);
       stage.setScene(scene);

       prevStage.close();

       stage.show();
    }

}
查看更多
登录 后发表回答