[英]JavaFX getScene() returns null in initialize method of the controller
我昨天在JavaFX中构建了一个小应用程序。 我想在Controller类中获取应用程序的场景。 每次尝试在控制器类中获取场景时,都会出错。 我可以在Controller类的Button上设置OnKeyPressed方法,效果很好。 但是,如果选择了Button,它就只能工作正常。.我只能在Main-class方法replaceSceneContent中得到场景。 我已经读过这个问题 ,但是我在初始化方法中调用了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;
}
});
}}}
这是我应用程序中的1.1版。 我在setOnKeyPressed事件处理程序中添加了一个if子句。 控制器的初始化完成后,方法将布尔控制器controllerRunning设置为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!");
}
}
你可以做
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的键处理程序。 似乎这些都应该在场景中注册。 但是,我还是把它留在了你的问题中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.