3 Replies Latest reply: Mar 14, 2013 12:07 PM by James_D RSS

    Duplicate screen

    992634
      I want my program to display the exact same thing simultaneously in two different windows on startup. How can I make this happen?

      EDIT: I figured out how to show two screens by running another stage, but now only the second shows content rather than both. Why?
      package ca.study.controller;
      
      import java.io.IOException;
      import java.net.URL;
      
      import javafx.application.Application;
      import javafx.fxml.FXMLLoader;
      import javafx.scene.Scene;
      import javafx.scene.layout.AnchorPane;
      import javafx.scene.layout.BorderPane;
      import javafx.stage.Stage;
      import javafx.stage.StageStyle;
      
      // Constructor Class
      public class MainApp extends Application {
      
           // Properties
           private Stage primaryStage;
           private BorderPane rootLayout;
      
           @Override
           public void start(Stage primaryStage) {
                
                // set stage FXML
                this.primaryStage = primaryStage;
                this.primaryStage.setTitle("Stage I");
           //     this.primaryStage.setFullScreen(true);
      
                Stage secondaryStage = new Stage();
                secondaryStage.setTitle("Stage II");
                
                // load root layout (stage) FXML
                try { 
                     URL url = MainApp.class.getResource("/ca/study/view/AppStage.fxml");
                     FXMLLoader loader = new FXMLLoader(url);          
                     rootLayout = (BorderPane) loader.load();
                     Scene scene = new Scene(rootLayout);
                     primaryStage.setScene(scene);
                     secondaryStage.setScene(scene);
                     primaryStage.show();
                     secondaryStage.show();
                } catch (IOException e) {
                     e.printStackTrace();
                }
                showControlSceneController();
                
           }
           // return main stage
           public Stage getPrimaryStage() {
                return primaryStage;
           }
           
           // show scene (ControlSceneController.java)
           public void showControlSceneController() {
                // load (scene) FXML; set into centre of main layout
                try {
                     FXMLLoader loader = new FXMLLoader(MainApp.class.getResource("/ca/study/view/AppScene.fxml"));
                     AnchorPane overviewPage = (AnchorPane) loader.load();
                     rootLayout.setCenter(overviewPage);
                     // give controller access to mainApp
                     ControlSceneController controller = loader.getController();
                     controller.setMainApp(this);
                     
                } catch (IOException e) {
                     e.printStackTrace();
                }
           }
      
           public static void main(String[] args) {
                launch(args);
           }
      Edited by: cheese on 13-Mar-2013 12:26 PM
        • 1. Re: Duplicate screen
          James_D
          You can't add the same Scene to multiple stages. Bad things would happen if you could: for example, if the root of the Scene is a resizable node, the size of the root will be changed when the size of the stage is changed.

          If you want to create two equivalent scenes and show each in a window, refactor your code as follows:
          try {
            primaryStage.setScene(createScene());
            secondaryStage.setScene(createScene());
          } catch (IOException e) { ... }
          with
          private Scene createScene() throws IOException {
            URL url = MainApp.class.getResource("/ca/study/view/AppStage.fxml");
            FXMLLoader loader = new FXMLLoader(url);          
            rootLayout = (BorderPane) loader.load();
            return new Scene(rootLayout);
          }
          • 2. Re: Duplicate screen
            992634
            That didn't work for me; still only the second window is displaying anything. Am I doing this right at all?
            Also, is there a way to allow the second scene to dynamically reflect whatever I change on the first one (eg. draw a circle)?
            @Override
            public void start(Stage primaryStage) {
                 
                 // set stage FXML
                 this.primaryStage = primaryStage;
                 this.primaryStage.setTitle("Screen 1");
                 
                 Stage secondaryStage = new Stage();
                 secondaryStage.setTitle("Screen 2");
            
                 try { 
                      primaryStage.setScene(createScene());
                      secondaryStage.setScene(createScene());
                      primaryStage.show();
                      secondaryStage.show();
                 } catch (IOException e) {
                      e.printStackTrace();
                 }
                 showControlSceneController();
            }
            
            // return main stage
            public Stage getPrimaryStage() {
                 return primaryStage;
            }
            
            private Scene createScene() throws IOException {
                 URL url = MainApp.class.getResource("/ca/study/view/AppStage.fxml");
                 FXMLLoader loader = new FXMLLoader(url);
                 rootLayout = (BorderPane) loader.load();
                 return new Scene(rootLayout);
            }
            Edited by: cheese on 14-Mar-2013 9:30 AM
            • 3. Re: Duplicate screen
              James_D
              cheese wrote:
              That didn't work for me; still only the second window is displaying anything. Am I doing this right at all?
              This works fine for me:

              TwoWindows.java
              import java.io.IOException;
              
              import javafx.application.Application;
              import javafx.fxml.FXMLLoader;
              import javafx.scene.Scene;
              import javafx.scene.layout.Pane;
              import javafx.scene.paint.Color;
              import javafx.scene.shape.Circle;
              import javafx.stage.Stage;
              
              public class TwoWindows extends Application {
              
                   @Override
                   public void start(Stage primaryStage) throws IOException {
                        Stage secondaryStage = new Stage();
                        primaryStage.setScene(createScene());
                        secondaryStage.setScene(createScene());
                        primaryStage.setTitle("Stage 1");
                        secondaryStage.setTitle("Stage 2");
                        primaryStage.show();
                        secondaryStage.show();
                        secondaryStage.setX(secondaryStage.getX()+250);
                   }
                   
                   private Scene createScene() throws IOException {
                     Pane pane = FXMLLoader.load(getClass().getResource("TwoWindows.FXML"));
                     return new Scene(pane, 200, 200);
                   }
              
                   public static void main(String[] args) {
                        launch(args);
                   }
              }
              TwoWindows.fxml
              <?xml version="1.0" encoding="UTF-8"?>
              
              <?import javafx.scene.layout.Pane?>
              <?import javafx.scene.shape.Circle?>
              <?import javafx.scene.paint.Color?>
              
              <Pane xmlns:fx="http://javafx.com/fxml">
                   <Circle centerX="100" centerY="100" radius="50">
                   <fill>
                   <Color fx:constant="ANTIQUEWHITE"/>
                   </fill>
                   </Circle>
              </Pane>
              Also, is there a way to allow the second scene to dynamically reflect whatever I change on the first one (eg. draw a circle)?
              I don't know of an easy way to do that. The way I'd approach something like that would be to use an MVC architecture. Define a data model which encapsulates the data describing everything you want to display and have your controller observe the model and make changes in the view in response. The controller should process all user input by changing the model. Then you can create a single model: create your two views and their corresponding controllers and pass the same model to both controllers.