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?