Java FXML对象在使用前被删除

Java FXML对象在使用前被删除,java,javafx,garbage-collection,javafx-8,fxml,Java,Javafx,Garbage Collection,Javafx 8,Fxml,这是我的密码 @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, "M

这是我的密码

@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()
方法中,抛出了一个null指针异常。似乎
calendarContainer
initialize()
按键之间的某个时间点变为空。我检查了我的代码,在我的程序中,我没有改变
calendarContainer
的值或重新分配它,它只是在FXML文件中创建的

<HBox fx:id="calendarContainer" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" styleClass="calendarContainer" />


为什么FXML对象会被删除(可能是一个符合触发器要求的垃圾收集器?),而int却不会被删除?

不要将
应用程序
类用作控制器类:这会使跟踪哪些字段在类的哪些实例中初始化变得太困难

为什么会删除FXML对象

没有

注释为
@FXML
的字段仅在控制器中初始化。加载FXML文件时,
FXMLLoader
创建由
fx:controller
属性指定的类的实例,创建与FXML中的元素对应的对象,然后将控制器中的字段设置为它创建的对象。最后,它在控制器上调用
initialize()


因此,在本例中,
calendarContainer
在控制器中初始化(这就是为什么在
initialize()
方法中会看到一个非空值),但在调用
start()
应用程序
类的实例中从未初始化它。所以它不会在某个时刻突然变为空:它总是空的

您应该为控制器创建一个单独的类:

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
属性)

现在,您
应用程序
类可以执行以下操作:

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对象

没有

注释为
@FXML
的字段仅在控制器中初始化。加载FXML文件时,
FXMLLoader
创建由
fx:controller
属性指定的类的实例,创建与FXML中的元素对应的对象,然后将控制器中的字段设置为它创建的对象。最后,它在控制器上调用
initialize()


因此,在本例中,
calendarContainer
在控制器中初始化(这就是为什么在
initialize()
方法中会看到一个非空值),但在调用
start()
应用程序
类的实例中从未初始化它。所以它不会在某个时刻突然变为空:它总是空的

您应该为控制器创建一个单独的类:

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
属性)

现在,您
应用程序
类可以执行以下操作:

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


    }

}

calendarContainer
仅在控制器中初始化。它没有在启动应用程序时创建的
应用程序
实例中初始化,该实例是调用
start()
的对象。基本上,当对
应用程序
和控制器使用同一类时,它太容易混淆。为控制器创建其他类。
calendarContainer
仅在控制器中初始化。它没有在启动应用程序时创建的
应用程序
实例中初始化,该实例是调用
start()
的对象。基本上,当对
应用程序
和控制器使用同一类时,它太容易混淆。为控制器创建一个不同的类。好的,我知道它是在控制器中初始化的。但是在初始化之后,它不应该在应用程序类中保持相同的值吗?@A.S.“保持初始化”是什么意思?您有两个对象。每一个都有一个
calendarContainer
字段。这些字段中只有一个被初始化,另一个总是空的。但是我通过分离类使其工作,所以谢谢:)好的,我知道它是在控制器中初始化的。但是在初始化之后,它不应该在应用程序类中保持相同的值吗?@A.S.“保持初始化”是什么意思?您有两个对象。每一个都有一个
calendarContainer
字段。这些字段中只有一个被初始化过,另一个总是空的。但是我通过分离类来实现它,所以谢谢:)