I am trying to work with custom controls in JavaFX and multiple FXML files. I create a custom control:
public class PetListGUIManager extends BorderPane { @FXML ListView<String> petList; private PetManager pm; public PetListGUIManager() { try { FXMLLoader loader = new FXMLLoader( getClass().getResource("PetList.fxml")); loader.setRoot( this ); loader.setController( this ); loader.load(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } pm = new PetManager(); ObservableList<String> items = FXCollections.observableArrayList( pm.getDisplayablePets() ); petList.setItems( items ); } @FXML public void handleButtonAction( ActionEvent event ) { Button b = (Button) event.getSource(); b.setText("Clicked!"); } } Using this FXML file:
<fx:root type="javafx.scene.layout.BorderPane" xmlns:fx="http://javafx.com/fxml"> <bottom> <Button onAction="#handleButtonAction" text="Click Me!" /> </bottom> <center> <ListView fx:id="petList" prefHeight="200.0" prefWidth="200.0" /> </center> </fx:root> Then I use this other main program:
public class TestMain extends Application { PetListGUIManager pm; @FXML FlowPane mainPane; @Override public void start(Stage stage) throws Exception { Parent root = FXMLLoader .load(getClass().getResource("Main.fxml")); Scene scene = new Scene(root); stage.setTitle("Test Main"); stage.setScene(scene); stage.show(); pm = new PetListGUIManager(); } /** * Purpose: * @param args */ public static void main(String[] args) { Application.launch( args ); } @FXML public void doSomething( ActionEvent ae ) { System.out.println( "In do something: " + mainPane ); ObservableList<Node> children = mainPane.getChildren( ); System.out.println( "Children are " + children ); children.add( pm ); } } Which uses this FXML file:
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="TestMain"> <children> <FlowPane fx:id="mainPane" prefHeight="400.0" prefWidth="600.0" > <Button text="Click here to start" onAction="#doSomething"/> </FlowPane> </children> </AnchorPane> When I click the button in the main window - which should load the custom control I get a java.lang.reflect.InvocationTargetException exception caused by: java.lang.NullPointerException: Children: child node is null: parent = FlowPane[id=mainPane]
What am I missing here?
Second question: You may notice I arbitrarily added a button to my main window so when it was clicked I could then load my BorderPane custom control class. Ideally I would like to do this directly in the start method of TestMain but mainPane is null in the start method - when does it become not null?