FXML 对象在使用前被删除
FXML object getting deleted before its used
这是我的代码
@FXML
public ScrollPane mainScrollPane;
@FXML
public Label dateScrollerLabel;
@FXML
public HBox calendarContainer;
int x = 5;
@Override
public void start(Stage primaryStage) throws Exception {
scene = JavaFXUtils.createScene(1000, 600, "Main.fxml", this);
primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/assets/resources/icon/icon_256.png")));
primaryStage.setTitle("HWP");
primaryStage.show();
//*****//
scene.addEventHandler(KeyEvent.KEY_PRESSED, this::keyPressed);
}
public void initialize() {
System.out.println(x); // not null
System.out.println(calendarContainer); // not null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // no nullpointer exception
}
private void keyPressed(KeyEvent keyEvent) {
switch (keyEvent.getCode()) {
case A:
System.out.println(x); // not null
System.out.println(calendarContainer); // null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // nullpointer exception
break;
}
}
我能够 运行 以下行 initialize()
方法中没有任何错误:
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer);
但是,当我 运行 之后的完全相同的代码时,在 keyPressed()
方法中,抛出了空指针异常。似乎 calendarContainer
在 initialize()
和 keyPressed
之间的某个时间点变为空。我检查了我的代码,在我的程序中,我从未更改 calendarContainer
的值或重新分配它,它仅在 FXML 文件中创建。
<HBox fx:id="calendarContainer" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" styleClass="calendarContainer" />
为什么 FXML 对象被删除(也许是触发快乐的垃圾收集器?)但 int 却没有?
不要使用 Application
class 作为控制器 class:很难跟踪在 [=41] 的哪些实例中初始化了哪些字段=].
Why does the FXML object get deleted
没有。
带注释的字段 @FXML
仅在控制器中初始化。当您加载 FXML 文件时,FXMLLoader
创建由 fx:controller
属性指定的 class 的实例,创建与 FXML 中的元素对应的对象,然后设置字段 在控制器中到它创建的对象。最后,它在控制器上调用 initialize()
。
所以在这种情况下,calendarContainer
在控制器中初始化(这就是为什么您在 initialize()
方法中看到 non-null 值),但它从未在Application
class 的实例,在其上调用 start()
。所以它不会在某个时候突然变成空:它总是空的。
您应该为控制器创建一个单独的 class:
public class Controller {
@FXML
private ScrollPane mainScrollPane;
@FXML
private Label dateScrollerLabel;
@FXML
private HBox calendarContainer;
public void initialize() {
System.out.println(x); // not null
System.out.println(calendarContainer); // not null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // no nullpointer exception
}
public void keyPressed(KeyEvent keyEvent) {
switch (keyEvent.getCode()) {
case A:
System.out.println(x); // not null
System.out.println(calendarContainer); // null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // nullpointer exception
break;
}
}
}
(并更新 FXML 文件中的 fx:controller
属性)。
现在你Application
class可以做到:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// Not sure what this does, but you probably can't use it without some
// modification.
// scene = JavaFXUtils.createScene(1000, 600, "Main.fxml", this);
// assuming path is correct:
FXMLLoader loader = new FXMLLoader(getClass().getResource("Main.fxml"));
Scene scene = new Scene(loader.load(), 1000, 600);
Controller controller = loader.getController();
scene.addEventHandler(KeyEvent.KEY_PRESSED, controller::keyPressed);
primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/assets/resources/icon/icon_256.png")));
primaryStage.setTitle("HWP");
primaryStage.show();
}
}
这是我的代码
@FXML
public ScrollPane mainScrollPane;
@FXML
public Label dateScrollerLabel;
@FXML
public HBox calendarContainer;
int x = 5;
@Override
public void start(Stage primaryStage) throws Exception {
scene = JavaFXUtils.createScene(1000, 600, "Main.fxml", this);
primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/assets/resources/icon/icon_256.png")));
primaryStage.setTitle("HWP");
primaryStage.show();
//*****//
scene.addEventHandler(KeyEvent.KEY_PRESSED, this::keyPressed);
}
public void initialize() {
System.out.println(x); // not null
System.out.println(calendarContainer); // not null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // no nullpointer exception
}
private void keyPressed(KeyEvent keyEvent) {
switch (keyEvent.getCode()) {
case A:
System.out.println(x); // not null
System.out.println(calendarContainer); // null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // nullpointer exception
break;
}
}
我能够 运行 以下行 initialize()
方法中没有任何错误:
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer);
但是,当我 运行 之后的完全相同的代码时,在 keyPressed()
方法中,抛出了空指针异常。似乎 calendarContainer
在 initialize()
和 keyPressed
之间的某个时间点变为空。我检查了我的代码,在我的程序中,我从未更改 calendarContainer
的值或重新分配它,它仅在 FXML 文件中创建。
<HBox fx:id="calendarContainer" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" styleClass="calendarContainer" />
为什么 FXML 对象被删除(也许是触发快乐的垃圾收集器?)但 int 却没有?
不要使用 Application
class 作为控制器 class:很难跟踪在 [=41] 的哪些实例中初始化了哪些字段=].
Why does the FXML object get deleted
没有。
带注释的字段 @FXML
仅在控制器中初始化。当您加载 FXML 文件时,FXMLLoader
创建由 fx:controller
属性指定的 class 的实例,创建与 FXML 中的元素对应的对象,然后设置字段 在控制器中到它创建的对象。最后,它在控制器上调用 initialize()
。
所以在这种情况下,calendarContainer
在控制器中初始化(这就是为什么您在 initialize()
方法中看到 non-null 值),但它从未在Application
class 的实例,在其上调用 start()
。所以它不会在某个时候突然变成空:它总是空的。
您应该为控制器创建一个单独的 class:
public class Controller {
@FXML
private ScrollPane mainScrollPane;
@FXML
private Label dateScrollerLabel;
@FXML
private HBox calendarContainer;
public void initialize() {
System.out.println(x); // not null
System.out.println(calendarContainer); // not null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // no nullpointer exception
}
public void keyPressed(KeyEvent keyEvent) {
switch (keyEvent.getCode()) {
case A:
System.out.println(x); // not null
System.out.println(calendarContainer); // null
currentSchedule = new Schedule(mainScrollPane, dateScrollerLabel, calendarContainer); // nullpointer exception
break;
}
}
}
(并更新 FXML 文件中的 fx:controller
属性)。
现在你Application
class可以做到:
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// Not sure what this does, but you probably can't use it without some
// modification.
// scene = JavaFXUtils.createScene(1000, 600, "Main.fxml", this);
// assuming path is correct:
FXMLLoader loader = new FXMLLoader(getClass().getResource("Main.fxml"));
Scene scene = new Scene(loader.load(), 1000, 600);
Controller controller = loader.getController();
scene.addEventHandler(KeyEvent.KEY_PRESSED, controller::keyPressed);
primaryStage.setScene(scene);
primaryStage.getIcons().add(new Image(Main.class.getResourceAsStream("/assets/resources/icon/icon_256.png")));
primaryStage.setTitle("HWP");
primaryStage.show();
}
}