Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
553 views
in Technique[技术] by (71.8m points)

java - JavaFX getScene() returns null in initialize method of the controller

I built a small application in JavaFX yesterday. I wanted to get the Scene of the application in the Controller class. I got an error every time I tried to get the scene in the controller class. I could set the OnKeyPressed-method on a Button in the Controller class, works fine. But it works only fine if the Button is selected.. I can get the scene in the Main-class method replaceSceneContent only. I have read this question already, but I call the getScene()-method in the initialize-method?? Thanks for any ideas!

Main class:

public class Main extends Application {

private Stage stage;

public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {
    stage = primaryStage;
    gotoMenu();
    primaryStage.show();
}

public void gotoMenu() {
    try {
        MenuController menu = new MenuController();
        menu = (MenuController) replaceSceneContent("Menu.fxml");
        menu.setApp(this);
    } catch (Exception ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private Node replaceSceneContent(String fxml) throws Exception {
    FXMLLoader loader = new FXMLLoader();
    @SuppressWarnings("resource")
    InputStream in = Main.class.getResourceAsStream(fxml);
    loader.setBuilderFactory(new JavaFXBuilderFactory());
    loader.setLocation(Main.class.getResource(fxml));
    BorderPane page;
    try {
        page = (BorderPane) loader.load(in);
    } finally {
        in.close();
    }
    page.setOnKeyPressed(event -> {
        switch (event.getCode()) {
        case F11:
            if (stage.isFullScreen()) {
                stage.setFullScreen(false);
            } else {
                stage.setFullScreen(true);
            }
            break;
        default:
            break;
        }
    });
    Scene scene = new Scene(page);
    page.prefWidthProperty().bind(scene.widthProperty());
    page.prefHeightProperty().bind(scene.heightProperty());
    stage.setScene(scene);
    return (Node) loader.getController();
}}

Controller class:

public class MenuController extends BorderPane implements Initializable {

Main application;

@FXML
private Button button;

public void setApp (Main application) {
    this.application = application;
}

@Override
public void initialize(URL location, ResourceBundle resources) {
    button.getScene().setOnKeyPressed(e -> {
        switch(e.getCode()) {
        case A:
            System.out.println("A pressed!");
            break;
        default:
            break;
        }
    });
}}}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Here's version 1.1 from my app. I added an if-clause to the setOnKeyPressed event handler. After the initialization of the controller is complete, a method turns the boolean controllerRunning to true. Finally I removed the InputStream, it's not needed.

If somebody needs an example:

Main class:

public class Main extends Application {

private Stage stage;
private boolean controllerRunning = false;
MenuController menu;

public void setControllerRunning(boolean controllerRunning) {
    this.controllerRunning = controllerRunning;
}

public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {
    stage = primaryStage;
    gotoMenu();
    primaryStage.show();
}

public void gotoMenu() {
    try {
        menu = new MenuController();
        menu = (MenuController) replaceSceneContent("Menu.fxml");
        menu.setApp(this);
        menu.keyFunctions();
    } catch (Exception ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private Node replaceSceneContent(String fxml) throws Exception {
    FXMLLoader loader = new FXMLLoader();
    loader.setBuilderFactory(new JavaFXBuilderFactory());
    loader.setLocation(Main.class.getResource(fxml));
    BorderPane page;
    try {
        page = (BorderPane) loader.load();
    } finally {
    }
    page.setOnKeyPressed(event -> {
        if (controllerRunning) {
            switch (event.getCode()) {
            case A:
                menu.printA();
                break;
            default:
                break;
            }
        }
        switch (event.getCode()) {
        case F11:
            if (stage.isFullScreen()) {
                stage.setFullScreen(false);
            } else {
                stage.setFullScreen(true);
            }
            break;
        default:
            break;
        }
    });
    Scene scene = new Scene(page);
    page.prefWidthProperty().bind(scene.widthProperty());
    page.prefHeightProperty().bind(scene.heightProperty());
    stage.setScene(scene);
    return (Node) loader.getController();
}}

controller class:

public class MenuController extends BorderPane{

Main application;

@FXML
private Button button;

public void setApp (Main application) {
    this.application = application;
}

public void keyFunctions() {
    application.setControllerRunning(true);
}
public void printA() {
    System.out.println("A!");
}
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...