Accessing node from outside its controller JavaFX - MVC - javafx

I'm building a weather application. There are 2 scenes with 2 controller files. One is a main screen and the other one is for "settings". The main FXML contains a label, which must be turned on/off in the settings page, if the user does not want to see that extra bit of information. My question is how to setVisible that label from the controller class of the setting page, if it's possible at all.
Thanks for your help

I'm assuming the settings scene only comes up when the user clicks a button on the main screen. I have had to handle the same situation in my code recently. Here is a great tutorial that handles this situation:
http://code.makery.ch/library/javafx-2-tutorial/part1/
1.) In your MainScene Controller you will reference the main class and call its function to pop up the Settings Scene.
2.) In your main class you will have a function that pops up the Settings Scene
3.) After the Settings Scene is closed it will pass the value back to the MainScene Controller through the Main class and based on the returned value you can set the label.
1.) Your MainController for your Main scene will have a reference to the main class and a function to call the Settings Scene through the main class.
public class MainController {
#FXML
private Label label;
#FXML
private Button Settings;
// Reference to the main application
private MainApp mainApp;
/**
* The constructor.
* The constructor is called before the initialize() method.
*/
public MainController() {
}
/*Tie this function to your button that pops up Settings */
private void handleSettingsButton() {
/* Here you call a function in the main class and pass the label
* to the settings scene controller */
boolean show = mainApp.showSettingsScene(label);
if (show) {
label.isVisible("True");
}
else {
label.isVisible("False");
}
}
/**
* Is called by the main application to give a reference back to itself.
*
* #param mainApp
*/
public void setMainApp(MainApp mainApp) {
this.mainApp = mainApp;
}
}
2.) In your main class (not to be confused with your main scene) you load the Main scene and call the setMainApp function to give your controller a reference back to the Main Class.
public class MainApp extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Main");
/*Right when the app is loaded the MainScene shows up.*/
try {
// Load the root layout from the fxml file
FXMLLoader loader = new FXMLLoader(MainApp.class.getResource("view/MainScene.fxml"));
/* Get a reference to the controller instance of the main Scene */
mainSceneController = loader.getController();
/*Allow the controller to talk to the main class */
mainSceneController.setMainApp(this);
rootLayout = (BorderPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
// Exception gets thrown if the fxml file could not be loaded
e.printStackTrace();
}
}
/**
* Returns the main stage.
* #return
*/
public Stage getPrimaryStage() {
return primaryStage;
}
/*This function referenced in your main controller will show the Settings
*Scene and wait to see what the user has selected for the visible or not
*visible selection. We need to pass the label to it as well, so we
*accurately load the Settings Scene with the current state of the label
*/
public boolean showSettingsScene(Label label) {
try {
// Load the fxml file and create a new stage for the popup
FXMLLoader loader = new FXMLLoader(MainApp.class.getResource("view/SettingsScene.fxml"));
settingsSceneController = loader.getController();
/* Here we send the label to the controller instance of the Settings
* Scene */
controller.setLabel(label);
AnchorPane page = (AnchorPane) loader.load();
Stage dialogStage = new Stage();
dialogStage.setTitle("Settings");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage);
Scene scene = new Scene(page);
dialogStage.setScene(scene);
/* Show the dialog and wait until the user closes it*/
dialogStage.showAndWait();
/*Return the value that the user has selected for visible or not */
return controller.isShowOrHide();
} catch (IOException e) {
// Exception gets thrown if the fxml file could not be loaded
e.printStackTrace();
return false;
}
}
public static void main(String[] args) {
launch(args);
}
}
3.) Your Settings Scene Controller will look something like the following:
import...
public class SettingsSceneController{
#FXML private ComboBox showOrHide;
private Stage dialogStage;
private Boolean show = false;
private Label label;
/**
* Initializes the controller class. This method is automatically called
* after the fxml file has been loaded.
*/
#FXML
private void initialize() {
;I don't know what you have, but if you use a Combobox...
showOrHide.getItems().addAll(
"Show",
"Hide",);
}
/**
* Sets the stage of this dialog.
* #param dialogStage
*/
public void setDialogStage(Stage dialogStage) {
this.dialogStage = dialogStage;
}
/*The label that was passed from Main Scene Controller to Main Class to
* here is now used in the function to update the Combobox with the
* current status of the label */
public void setLabel(Label label) {
this.label = label;
if(label.isVisible){
showOrHide.setValue("Show");
show = true;
}
else{
showOrHide.setValue("Hide");
show = false;
}
}
/**
* Returns true if the user clicked OK, false otherwise.
* #return
*/
public boolean isShowOrHide() {
return show;
}
/**
* Called when the user clicks ok. Attach this in Scene Builder,to the OK,
* Enter or Apply or whatever you called it button of the Settings Scene
* It will reflect any change made to the combobox.
*/
#FXML
private void handleOk() {
if (showOrHide.getValue().toString() == "Show") {
show= true;
}
else{
show = false;
}
dialogStage.close();
}
/**
* Called when the user clicks cancel if you have a cancel button.
*/
#FXML
private void handleCancel() {
dialogStage.close();
}
}
}
I took most of this code from the tutorial and custom tailored it to your solution. It is kind of bouncing around to three classes, but if you think on it a little bit you can see how they are communicating between the controllers using the main class to facilitate it. I did not test this, but it should be pretty close to what you need.

Related

accessing a Pane from another class in javafx

I am unable to access from another class, I have created two pane with different controllers in one FXML File, second pane has to move around the first pane, on Click Action, and I have loaded an FXML file in second pane, also successfully moved the pane one time, but the second time I want to move it from second controller, but it is giving me an NullPointerException.
this is my main controller where I have moved the pane:
public class MainController implements Initializable {
#FXML
private Pane searchPane;
#FXML
private Pane secondPane;
private TranslateTransition nextTransition;
public Pane getSecondPane() {
return secondPane; // Accessing Pane with this getter method
}
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
private void nextBtnAction(ActionEvent event) {
try {
Parent pessFxml = FXMLLoader.load(getClass().getResource("firstPane.fxml"));
secondPane.getChildren().add(pessFxml);
nextTransition = new TranslateTransition(Duration.millis(300), secondPane);
nextTransition.setToX(searchPane.getLayoutX()-secondPane.getLayoutX());
nextTransition.play();
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Form does not found" ,ex.toString(),0);
}
}
}
this is SecondController where I am accessing the pane to move it back smoothly, but its throwing NullPointerException:
please tell me how to solve this
public class SecondController implements Initializable {
MainController mainControll;
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
private void backBtnPessAction(ActionEvent event) {
//here i am putting the second pane to move back
TranslateTransition back = new TranslateTransition(Duration.millis(300), mainControll.getSecondPane());
back.setToX(mainControll.getSecondPane().getLayoutX()-750);
back.play();
}
}
MainController is never initialized in SecondController. You should pass it when creating second controller in nextBtnAction.
MainController code:
private void nextBtnAction(ActionEvent event) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("firstPane.fxml"));
Parent pessFxml = loader.load();
SecondController controller = (SecondController)loader.getController();
controller.setMainController(this);
secondPane.getChildren().add(pessFxml);
nextTransition = new TranslateTransition(Duration.millis(300), secondPane);
nextTransition.setToX(searchPane.getLayoutX()-secondPane.getLayoutX());
nextTransition.play();
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Form does not found" ,ex.toString(),0);
}
}
SecondController:
public void setMainController(MainController controller) {
this.mainControll = controller;
}

How to close a dialog box programmatically

please I need some assistance. I have this java fx project I am working on. The idea is to prevent the default windows close button behavior, and only close the dialog if login is successful.
Below is how I am able to set the dialog and prevent dialog closing.
public class MainController extends Application implements Initializable{
// Create a dialog
private Dialog<Pair<String, String>> dialog = new Dialog<>();
/*Login resources*/
#FXML // fx:id="loginBtn"
private Button loginBtn; // Value injected by FXMLLoader
#FXML // fx:id="usernameTxt"
private TextField usernameTxt; // Value injected by FXMLLoader
#FXML // fx:id="loginProgressIndicator"
private ProgressIndicator loginProgressIndicator; // Value injected by FXMLLoader
#FXML // fx:id="passwordTxt"
private PasswordField passwordTxt; // Value injected by FXMLLoader
#FXML // fx:id="statusLbl"
private Label statusLbl; // Value injected by FXMLLoader
#FXML
void login(ActionEvent event) {
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
stage.fireEvent(
new WindowEvent(
stage,
WindowEvent.WINDOW_CLOSE_REQUEST
)
);
}
/*Main Menu resources*/
#FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
#FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
#FXML // fx:id="visitBtn"
private Button visitBtn; // Value injected by FXMLLoader
#FXML // fx:id="reportBtn"
private Button reportBtn; // Value injected by FXMLLoader
#FXML // fx:id="setupBtn"
private Button setupBtn; // Value injected by FXMLLoader
#FXML
void report(ActionEvent event) {
}
#FXML
void setup(ActionEvent event) {
}
#FXML
void visit(ActionEvent event) {
System.out.println("Visit Button Pressed.");
}
/**
* The main entry point for all JavaFX applications.
* The start method is called after the init method has returned,
* and after the system is ready for the application to begin running.
* <p>
* <p>
* NOTE: This method is called on the JavaFX Application Thread.
* </p>
*
* #param primaryStage the primary stage for this application, onto which
* the application scene can be set. The primary stage will be embedded in
* the browser if the application was launched as an applet.
* Applications may create other stages, if needed, but they will not be
* primary stages and will not be embedded in the browser.
*/
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
Scene scene = new Scene(root);
primaryStage.setTitle("Main Menu - PEHCS Point of Sale");
primaryStage.setScene(scene);
primaryStage.show(); //This will display the main menu
dialog.setTitle("Login - PEHCS Point of Sale");
dialog.setHeaderText(null);
// Get the Stage.
Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
// Add a custom icon.
stage.getIcons().add(new Image(this.getClass().getResource("activa.jpg").toString()));
/*This section prevents the dialog from closing when we press on the window X button*/
Window window = dialog.getDialogPane().getScene().getWindow();
window.setOnCloseRequest(new EventHandler<WindowEvent>() {
/**
* Invoked when a specific event of the type for which this handler is
* registered happens.
*
* #param event the event which occurred
*/
#Override
public void handle(WindowEvent event) {
event.consume();
}
});
/*Set th content of that dialog to be the login.fxml resource file*/
dialog.getDialogPane().setContent(FXMLLoader.load(getClass().getResource("login.fxml")));
Optional<Pair<String, String>> result = dialog.showAndWait();
result.ifPresent(usernamePassword -> {
System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
});
}
/**
* Called to initialize a controller after its root element has been
* completely processed.
*
* #param location The location used to resolve relative paths for the root object, or
* <tt>null</tt> if the location is not known.
* #param resources The resources used to localize the root object, or <tt>null</tt> if
*/
#Override
public void initialize(URL location, ResourceBundle resources) {
assert visitBtn != null : "fx:id=\"visitBtn\" was not injected: check your FXML file 'main2.fxml'.";
assert reportBtn != null : "fx:id=\"reportBtn\" was not injected: check your FXML file 'main2.fxml'.";
assert setupBtn != null : "fx:id=\"setupBtn\" was not injected: check your FXML file 'main2.fxml'.";
assert loginBtn != null : "fx:id=\"loginBtn\" was not injected: check your FXML file 'login.fxml'.";
assert usernameTxt != null : "fx:id=\"usernameTxt\" was not injected: check your FXML file 'login.fxml'.";
assert loginProgressIndicator != null : "fx:id=\"loginProgressIndicator\" was not injected: check your FXML file 'login.fxml'.";
assert passwordTxt != null : "fx:id=\"passwordTxt\" was not injected: check your FXML file 'login.fxml'.";
assert statusLbl != null : "fx:id=\"statusLbl\" was not injected: check your FXML file 'login.fxml'.";
}
public static void main(String[] args) {
launch(args);
}
The window close event is being consume in the on start method and it works. Now I want to close this dialog in th login methos. This is where I am stuck. Please I need help.
Thanks in advance.
To close the window programmatically, all you need is
#FXML
void login(ActionEvent event) {
dialog.close();
}
Note that this will not trigger an onCloseRequest handler, which is only invoked for an external request to close the window (see docs).

how to share data between two stages in javafx

I have two fxml window login and main window.Their respective controllers are given below:
public class MainwindowController extends Stage implements Initializable {
#FXML private Button Send;
#FXML private TextField txtBcast;
#FXML private ListView listviewUsers;
#FXML Label lblDisplayName;
/**
* Initializes the controller class.
* #param url
* #param rb
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
ObservableList<String> chat =FXCollections.observableArrayList ("default");
listviewUsers.setItems(chat);
}
public void setLblName(String msg){
lblDisplayName.setText(msg);
}
#FXML public void ActionSend(ActionEvent e){
send();
txtBcast.setText("");
}
private void send() {
if (txtBcast.getText().isEmpty())
return;
// chatManager.sendPublicMsg(format,txtBcast.getText());
}
/**
*
* #param e
* #throws Exception
*/
#FXML public void ActionUserSelected( MouseEvent e) throws Exception{
// String lineRest = e.getActionCommand();
if(e.getClickCount()==2)
{
if(!listviewUsers.getSelectionModel().isEmpty())
{
String str=(String)listviewUsers.getSelectionModel().getSelectedItem();
Parent main= FXMLLoader.load(getClass().getResource("/letschat/fxwindows/Usertab.fxml"));
Scene scene = new Scene(main);
Stage stage = new Stage();
stage.setTitle(str);
stage.setScene(scene);
stage.show();
}
else { JOptionPane.showMessageDialog(null, "Oops! it seems you are trying to click the list view"); }
}
//Stage pstage = (Stage)listUsers.getScene().getWindow();
//pstage.close();
}
}
And
public class LoginwindowController extends Stage implements Initializable {
#FXML private LoginwindowController loginwindowController;
#FXML private MainwindowController mainwindowController;
#FXML private Button btnSignIn;
#FXML private TextField txtDisplayName;
#FXML private ToggleGroup Gender;
#FXML private ComboBox comboStatus;
/**
* Initializes the controller class.
* #param url
* #param rb
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
ObservableList<String> items =FXCollections.observableArrayList ("Online","Offline");
comboStatus.setItems(items);
writeToTextField();
}
public void writeToTextField() {
String username = System.getProperty("user.name");
txtDisplayName.setText(""+ username);
}
#FXML protected void ActionSignIn(ActionEvent event) throws Exception {
mainwindowController.setLblName(txtDisplayName.getText());
InetAddress addr = InetAddress.getLocalHost();
if(addr.isLoopbackAddress())
{
Dialogs.create().message("Oops! It seems you are not connected to any network..\n :(").showError();
}
else{
start(txtDisplayName.getText());// start chat manager
Parent root= FXMLLoader.load(getClass().getResource("/letschat/fxwindows/Mainwindow.fxml"));
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setTitle("LetsChat-Welcome "+ txtDisplayName.getText());
// Context.getInstance().setDisplayName(txtDisplayName.getText());
stage.setScene(scene);
stage.getIcons().add(new Image("/letschat/images/logo.png"));
Stage pstage = (Stage)btnSignIn.getScene().getWindow();
stage.show();
pstage.close();
}
}
private void start(String name) {
try {
ChatManager ic = new ChatManager(name);
ic.start();
} catch (Exception ex) {
Dialogs.create().message( "Could not start the chat session\nCheck that there no other instances running :(").showError();
}
}
}
I want the label lblDisplayName in main window updated with text from txtDisplay Name in login window when user clicks signin button.can someone help how to do so..soon plz
There are various ways to do this, in your case Login will create the other stage so an easy way is to create a new FXML loader (variable name: myLoader) and, if you want to pass the username of the user as constructor argument you can use myLoader.setControllerFactory and as return:
return clazz == MyController.class ? new MyController(userName) : null;
MyController is the name of the Controller where you want to read the username
If you want to use set methods, with getController you get the controller instance and call the set method (e.g, myController.setUsername());
To create a custom FXML
FXMLLoader myLoader = new FXMLLoader(<if you use relative paths, here you should pass the position);
remember to call the load() because the URI overload is static. (i.e, use getResourceAsStream).
If your application is large and complex, you could use EventBus (which I prefer everywhere..)
I'm not sure I completely understand the relationship between the two controllers, and which are the FXML files that correspond to the controllers, but it looks like the LoginWindowController loads MainWindow.fxml, and I'm guessing that MainWindowController is the controller for MainWindow.fxml.
In that case, you can just do
#FXML protected void ActionSignIn(ActionEvent event) throws Exception {
InetAddress addr = InetAddress.getLocalHost();
if(addr.isLoopbackAddress())
{
Dialogs.create().message("Oops! It seems you are not connected to any network..\n :(").showError();
}
else{
start(txtDisplayName.getText());// start chat manager
FXMLLoader loader = new FXMLLoader(getClass().getResource("/letschat/fxwindows/Mainwindow.fxml"));
Parent root= loader.load();
MainWindowController mainWindowController = loader.getController();
mainWindowController.setLblName(txtDisplayName.getText());
Scene scene = new Scene(root);
Stage stage = new Stage();
stage.setTitle("LetsChat-Welcome "+ txtDisplayName.getText());
// Context.getInstance().setDisplayName(txtDisplayName.getText());
stage.setScene(scene);
stage.getIcons().add(new Image("/letschat/images/logo.png"));
Stage pstage = (Stage)btnSignIn.getScene().getWindow();
stage.show();
pstage.close();
}
}

JavaFX load FXML inside parent controller

I have a borderpane where I'm loading an fxml (alias FirstPanel) with relative controller inside of it and positioned in the center. The fxml contains a TableView and a button which should load another fxml (alias SecondPanel) and relative controller instead the first panel. Basically, the SecondPanel needs to show some details about the data selected in the table.
Is it possible to do it? How can I get the parent of my FirstPanel and use it for the SecondPanel instead of the first?
UPDATE
I've tried many solutions but without reach my goal. The application load the UsersMainPageController which contains only an AnchorPane like parent control, so this is the relative code:
[UsersMainPageController]
public class UsersMainPageController implements Initializable {
private PostOffice application;
#FXML
private AnchorPane ParentControl;
public void setApp(PostOffice application){
this.application = application;
}
public void loadPage(String pageName) {
try {
URL url = getClass().getResource(pageName);
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(url);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
AnchorPane page = (AnchorPane) fxmlLoader.load(url.openStream());
ParentControl.getChildren().clear();///name of pane where you want to put the fxml.
ParentControl.getChildren().add(page);
}
catch (IOException e) {
e.printStackTrace();
}
}
public void loadManageUsers () {
loadPage("UsersManage.fxml");
}
public void loadListUsers () {
loadPage("UsersList.fxml");
}
/**
* Initializes the controller class.
*/
#Override
public void initialize(URL url, ResourceBundle rb) {
loadListUsers();
}
}
loadListUsers calls UsersList.fxml with the relative controller UsersListController that contains a TableView with some records and some buttons. When I click a specific button, it should call loadManageUsers with relative controller UsersManageController which contains some fields for editing data and inserting new users. When users are edited or inserted, it should be able to return to the previous page with the TableView and clear the current page (in this case UsersManageController).
[UsersListController]
public class UsersListController implements Initializable {
private UsersMainPageController mainController;
#FXML
private void handleButtonEditAction(ActionEvent event) throws IOException {
mainController.loadManageUsers();
}
}
[UsersManageController]
public class UsersManageController implements Initializable {
private UsersMainPageController mainController;
#FXML
private void handleButtonBackAction(ActionEvent event) throws IOException {
mainController.loadListUsers();
}
}
When I click from the UsersListController the ButtonEdit to load the UsersManageController, I get this error:
Caused by: java.lang.NullPointerException
at postoffice.multiuser.UsersListController.handleButtonAggiornaAction(UsersListController.java:210)
... 50 more
you can add your child fxml into parent controller..
1.first just take a anchor pane and set its bounds where you want to put your FXML code.
now try this...
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
openNewWindow("Example.fxml");
}
});
you can pass fxml name into function...
public void openNewWindow(String FXMLFile)
{
//ChildNode child;
try {
URL url = getClass().getResource(FXMLFile);
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(url);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
AnchorPane page = (AnchorPane) fxmlLoader.load(url.openStream());
anchor.getChildren().clear();///name of pane where you want to put the fxml.
anchor.getChildren().add(page);
}
catch (IOException e) {
e.printStackTrace();
}
}

javafx fxml is null outside initialize()

In this code:
public class ESM extends Application {
private Stage primaryStage;
#FXML
private ToolBar mainToolBar;
#Override
public void start(final Stage stage) throws Exception {
try{
this.primaryStage = stage;
Parent root = FXMLLoader.load(getClass().getResource("/nz/co/great_ape/esm3/main_window.fxml"));
Scene scene = new Scene(root, 800, 700);
// Setup main stage to be full screen, no min or max buttons.
// TODO: How will this handle multiple screens? Apparently not well :-(
Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setWidth(bounds.getWidth());
primaryStage.setHeight(bounds.getHeight());
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setTitle("ESM three");
primaryStage.setScene(scene);
primaryStage.show();
System.out.println("This will fail because mainToolBar is null. Why?");
assert mainToolBar != null : "fx:id=\"mainToolBar\" was null check your FXML ";
} catch (Exception ex) {
Logger.getLogger(ESM.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Use initialize() to setup widgets from scenebuilder files, it is
* called by FXMLLoader.
*/
#FXML
public void initialize(){
System.out.println("initialize() But when here all is good and mainToolBar is a ToolBar.");
assert mainToolBar != null : "fx:id=\"mainToolBar\" was null check your FXML ";
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support.
*
* #param args The command line arguments.
*/
public static void main(String[] args) {
launch(args);
}
}
I cant see why it's got a value in the initialise() but in the start it's null. When debuging it's clear that initiialize() is called by FXMLLOader from inside start()
I was going to post the fxml but it does not seem to work as nothig shows in the preview. Any way, it's a real basic file, a BordePane and a ToolBar.
Any clues?
Always create a new class for your FXML Controller, don't try to reuse an Application class as a Controller class.
An Application instance is created by the JavaFX application launcher.
A Controller instance is created by the JavaFX FXML loader.
You don't supply the FXML that you use, but I am going to guess that it has it's Controller class erroneously set to be your application class.
So in your code, what happens is:
An instance of the application is created when you run the program (via the launch method).
In your application start method, you invoke the FXMLLoader, which instantiates a new Controller (in your case a new instance of the application class).
The FXMLLoader injects the #FXML tagged members into the new application object and invokes the initialize on the new object.
But your original application object doesn't know anything about the new application object and hence doesn't have a menu bar set in it.
In summary, to fix this:
Create a new controller class that the FXMLLoader can instantiate.
Change your fxml to reference the new controller class.
If your application really needs to reference the controller, then you can use the getController method on the FXML loader and in your controller class provide public methods to retrieve required elements (like your menu bar). See my answer to Passing Parameters JavaFX FXML for some more examples of this method.
import javafx.scene.control.ToolBar;
import javafx.fxml.FXML;
public class ESMController {
#FXML
private ToolBar mainToolBar;
public ToolBar getMainToolBar() { return mainToolBar; }
#FXML
public void initialize(){
assert mainToolBar != null : "fx:id=\"mainToolBar\" was null check your FXML ";
}
}

Resources