JavaFX getScene()在控制器的initialize方法中返回null

我昨天在JavaFX中构建了一个小应用程序。 我想在Controller类中获取应用程序的场景。 每次我尝试在控制器类中获取场景时都会出错。 我可以在Controller类的Button上设置OnKeyPressed方法,工作正常。 但是如果选择了Button,它的工作正常。我只能在Main-class方法replaceSceneContent中获取场景。 我已经读过这个问题了 ,但我在initialize-method中调用了getScene()方法? 谢谢你的任何想法!

主要课程:

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(); }} 

控制器类:

 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; } }); }}} 

你可以做

 private Node replaceSceneContent(String fxml) throws Exception { FXMLLoader loader = new FXMLLoader(); loader.setBuilderFactory(new JavaFXBuilderFactory()); loader.setLocation(Main.class.getResource(fxml)); BorderPane page = loader.load(); MenuController controller = loader.getController(); 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); scene.setOnKeyPressed(event -> { if (event.getCode() == KeyCode.A) { controller.printA(); } }); page.prefWidthProperty().bind(scene.widthProperty()); page.prefHeightProperty().bind(scene.heightProperty()); stage.setScene(scene); return controller ; } 

 public class MenuController extends BorderPane{ // existing code... public void printA() { System.out.println("A!"); } } 

只是一个评论:它使MenuController成为BorderPane (或任何其他UI类)的子类完全没有意义。 我把它留在了,以防你在其他地方需要它,但它完全违反了MVC模式。

另外,我不确定为什么你希望A的键处理程序在场景中,并且F11的键处理程序在场景的根目录上。 看来这些都应该在场景中注册。 但是,我再次将其留在了问题中。

这是我的应用程序的1.1版。 我在setOnKeyPressed事件处理程序中添加了一个if子句。 控制器初始化完成后,方法将布尔控制器运行转为true。 最后我删除了InputStream,不需要它。

如果有人需要一个例子:

主要课程:

 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(); }} 

控制器类:

 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!"); } }