1

I am new to javafX, have run through various tutorials, and googled extensively. I am attempting to write a multiscreen javaFX program whose second screen has a split pane, whose right pane should display a grid and a button. The framework I am using for multiple screens is copied form Angela Caiedo's MultipleScreens Framework tutorial ( https://github.com/acaicedo/JFX-MultiScreen/tree/master/ScreensFramework) .

What works: The screens framework is successful in terms of flipping between my multiple screens.

My problem: I click the button on screen 1 to move to screen 2. Screen 2 successfully shows. On screen 2 I click a button to populate data in my vBox. The code in my controller class for screen 2 is unable to access the vbox (or any other defined containers on this screen).

My main class sets up the controller screens.

public class FieldMapCreator extends Application {
    public static String mainID = "main";
    public static String mainFile = "MainMapFXMLDocument.fxml";
    public static String initialMapID = "initialMap";
    public static String initialMapFile = "FXMLMapPicture.fxml";
  @Override
  public void start(Stage stage) throws Exception {

    ScreensController mainContainer = new ScreensController();
    mainContainer.loadScreen(FieldMapCreator.mainID, FieldMapCreator.mainFile);
    mainContainer.loadScreen(FieldMapCreator.initialMapID, FieldMapCreator.initialMapFile);

    mainContainer.setScreen(FieldMapCreator.mainID);
    Group root = new Group();
    root.getChildren().addAll(mainContainer);
    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
  }
}

I get to the second screen by clicking a button on screen 1. Button1 code looks like:

@FXML
private void initialMapButtonAction(ActionEvent event) {
    myController.setScreen(FieldMapCreator.initialMapID);
}

Screen 2 has a button that when clicked executes a method that creates data for the vbox. The fxml for screen 2 is this:

<AnchorPane id="AnchorPane" fx:id="mainAnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="FieldMapCreator.FXMLMapPictureController">
   <children>
      <SplitPane fx:id="mapSplitPane" dividerPositions="0.29797979797979796" layoutX="3.0" layoutY="7.0" prefHeight="400.0" prefWidth="600.0">
        <items>
          <AnchorPane fx:id="anchorPaneLeft" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
               <children>
                  <Button fx:id="backButton" layoutX="14.0" layoutY="348.0" mnemonicParsing="false" onAction="#goToMainScreen" text="Back" />
               </children>
            </AnchorPane>
          <AnchorPane fx:id="anchorPaneRight" minHeight="0.0" minWidth="0.0" prefHeight="364.0" prefWidth="401.0">
               <children>
                  <Button fx:id="vBoxShowMap" layoutX="24.0" layoutY="346.0" mnemonicParsing="false" onAction="#buildMapFromNurseries" prefHeight="26.0" prefWidth="91.0" text="show map" />
                  <VBox fx:id="mapVBox" layoutX="24.0" layoutY="24.0" onMouseClicked="#vBoxMouseClicked" prefHeight="200.0" prefWidth="309.0" />
               </children></AnchorPane>
        </items>
      </SplitPane>
   </children>
</AnchorPane>

The code that fails is in the "showInitialMap()" method of the controller class for screen 2. When executed, the last line of this method "mapVBox.getChildren().add(root)", results in a null pointer exception. I expected this to be resolved via the fxml injection. I also tried the commented out code to retrieve "mapVBox" using scene lookup, but it also results in a null pointer exception. The controller code is below:

public class FXMLMapPictureController  implements Initializable, ControlledScreen  {

  ScreensController myController;
  static MyNode[][] mainField ;

  @FXML
  private AnchorPane mainAnchorPane;
  @FXML
  private static SplitPane mapSplitPane;
  @FXML
  private AnchorPane anchorPaneLeft;
  @FXML
  private static AnchorPane anchorPaneRight;
  @FXML
  private static VBox mapVBox;
  @FXML
  private Button vBoxShowMap;
  /**
   * Initializes the controller class.
   */
  @Override
  public void initialize(URL url, ResourceBundle rb) {
     // Should something be in here ??
  }

  public void goToMainScreen() {
    myController.setScreen(FieldMapCreator.mainID);
  }

  public void showInitialMap() {
    int row = userFieldMap.getNumRows();
    int col = userFieldMap.getNumCols();

    double gridWidth = 309/col;
    double gridHeight = 200/row;
    Group root = new Group();
    // initialize the field
    for (int idx = 0; idx < col; idx++) {
        for (int jdx = 0; jdx < row; jdx++) {
            // create plot
            Plot plot = new Plot(idx, jdx, "Plot" + idx + "/" + jdx);
            // Create node to hold the Plot
            MyNode node = new MyNode(idx*gridWidth, jdx*gridHeight, gridWidth, gridHeight, plot);
            // add plot to group
            root.getChildren().add(node);
        }
    }
    //Scene myScene = myController.getScene();
    //VBox mapVBox = (VBox)myScene.lookup("#mapVBox");
    mapVBox.getChildren().add(root);
  }

  @Override
  public void setScreenParent(ScreensController screenParent) {
    myController = screenParent;
  }

Is there something missing from the initialize() method? I'm wondering if I am not setting something correctly when I change screens. I am able to access the initial screen's containers without problem from all screen 1 methods including the initialize class. When I attempt the same in screen 2, I get the message "screen hasn't been loaded !!!"

Thanks for any help you can provide.

lynnj
  • 115
  • 1
  • 7

1 Answers1

1

You are using static fields as FXML injection targets which don't work in Java 8 and should not have been implemented to work in any other version, as static UI elements just don't make sense. Here's a bit more detailed answer. Having resorted to a static field most of the time means the software design of the application needs to be reconsidered.

Community
  • 1
  • 1
AlmasB
  • 3,377
  • 2
  • 15
  • 17
  • Thank you! I don't recall why I added "static" to the fields (inexperienced new user!) , but removing it solved the problem. The screen was not loading correctly which is why I could not access the containers. It now loads. – lynnj Jul 20 '15 at 16:20