1
votes

Im trying to change a scene in my application and one of the nodes needs to be updated directly after loading the scene, but the problem is is that the node has not been initialized yet so I always get NPE. How can I either force the node to be initialized or wait until all the nodes have been initialized before calling a method of that ndoe

I've never had success with trying to call a node, however it does seem to work if I call the node in an event(Such as a button press).

package za.holmes.PAT;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;

public class EventHandler implements Initializable {

    @FXML
    private AnchorPane changePane;
    @FXML
    private TextField IDField;
    @FXML
    private PasswordField passField;
    @FXML
    private Label errorField;
    @FXML
    private Label nameText;

    private User currentUser;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
    }

//    @FXML
//    private void initialize() {
//    }

    @FXML
    private void start(ActionEvent event) {
        ((Button) event.getSource()).setDisable(true);;
        System.out.println("Program started");
        try {
            System.out.println("Connecting to database");
            Class.forName("za.holmes.PAT.DataHandler");
        } catch (Exception e) {
            e.printStackTrace();
        }
        updateScreen("Login.fxml");
    }

    private void updateScreen(String fileName) {
        try {
            FXMLLoader loader = new FXMLLoader();
            AnchorPane pane = (AnchorPane)loader.load(Oldage.class.getResourceAsStream("/scenes/" + fileName));
            changePane.getChildren().setAll(pane);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //Init complete
    @FXML
    private void login(ActionEvent event) {
        String userIDText = "", passText = "";
        int user = 0;
        try {
            errorField.setVisible(false);
            userIDText = IDField.getText();
            passText = passField.getText();
            // This is a call to another method that gets the type of user 
            // attempting to log in(it will be 1)
            user = DataHandler.checkUser(userIDText, passText);
            switch (user) {
                case 0:
                    errorField.setVisible(true);
                    break;
                case 1:
                    updateScreen("Old.fxml");
                    currentUser = DataHandler.getInfoElder(userIDText);
                    nameText.setText("Hello");
                    break;
                case 2:
                    break;
                case 3:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

1
I don't see any code in the initialize function. Try wrapping the code in Platform.runlater.Sedrick
I'll try that but i'm not sure what runnable to parse?Michael Holmes
Platform.runLater(()->{//your code here!}):Sedrick
Unfortunately I can't put that in the initialize function because I use this controller for all of my FXML files and some of the files don't contain the "nameText" node so it would still give a null pointer exception.Michael Holmes
Sure, there's a workaround; simply only initialize a field if it isn't null. However, you don't want to use that workaround because you should not be using the same controller class for multiple FXML files in the first place. Refactor your controller class into multiple, distinct controller classes—one for each FXML file. If you need to communicate between controller instances, see questions such as Passing Parameters JavaFX FXML.Slaw

1 Answers

0
votes

Yeah, just don't use a single controller. Use multiple controllers and rather have the screens change by altering the visibility of the elements, rather than having the each "scene" be an entirely new FXML file