简体   繁体   English

控制器中的JavaFX 2 Window事件处理

[英]JavaFX 2 Window event handling in controllers

So I am trying to handle WINDOW_SHOWN event from my controller with code like this: 所以我正在尝试使用以下代码从控制器处理WINDOW_SHOWN事件:

@Override
public void initialize(URL url, ResourceBundle resourceBundle) {

    initializeDatePickers();
    System.out.println("payer number in initialize: " + payerNumber);

    URL location = getClass().getResource("/createUser.fxml");
    FXMLLoader loader = new FXMLLoader();

    try {
        Parent root = (Parent) loader.load(location.openStream());
        root.getScene().getWindow().setOnShown(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent event) {
                System.out.println("ONSHOWN");
            }
        });
    } catch (IOException e) {
        e.printStackTrace();
    }

}

But all I've got was endless cycle and program crash. 但是我所得到的只是无休止的循环和程序崩溃。 The code below didn't work either, it returns NullPointerException: 下面的代码也不起作用,它返回NullPointerException:

@FXML private AnchorPane createUserDialog; //my root pane

@Override
public void initialize(URL url, ResourceBundle resourceBundle) {

    createUserDialog.getScene().getWindow().addEventHandler(WindowEvent.WINDOW_SHOWN, 
      new EventHandler<WindowEvent>() {
        @Override
        public void handle(WindowEvent window) {
            System.out.println("ONSHOWN");
        }
    });

}

Implementing WindowEvent interface didn't work at all, don't know why. 实现WindowEvent接口根本行不通,不知道为什么。 So, how could I handle this event? 那么,我该如何处理此事件? And why I've got NullPointerException? 以及为什么我有NullPointerException? In docs said that initialize() calling only after root pane completely processed. 在docs中表示只有在根窗格完全处理后才调用initialize()

When the initialize() method is being executed, the root pane is completely constructed but is not added to a scene, or a window. 当执行initialize()方法时,根窗格已完全构建,但未添加到场景或窗口中。 (The initialize() method is executed as part of the execution of your FXMLLoader's load() method; check the code where you call that and you will see that you add the root to a scene and place it in a window after that.) So during the execution of intialize(), root.getScene() will return null. (initialize()方法是FXMLLoader的load()方法执行的一部分;要检查调用该代码的代码,您会看到将根添加到场景中,然后将其放置在窗口中。)因此,在执行intialize()期间,root.getScene()将返回null。

You can use a Binding to check when the window changes and attach a listener to it: 您可以使用Binding来检查窗口何时更改,并在其上附加一个侦听器:

final EventHandler<WindowEvent> shownHandler = new EventHandler<WindowEvent>() {
  @Override
  public void handle(WindowEvent event) {
    System.out.println("Shown");
  }
};
Bindings.<Window>select(createUserDialog.sceneProperty(), "window").addListener(new ChangeListener<Window>() {

    @Override
    public void changed(ObservableValue<? extends Window> observable,
            Window oldValue, Window newValue) {
        if (oldValue != null) {
            oldValue.removeEventHandler(WindowEvent.WINDOW_SHOWN, shownHandler);
        }
        if (newValue != null) {
            newValue.addEventHandler(WindowEvent.WINDOW_SHOWN, shownHandler);
        }
    }

});

This code assumes the root is only ever added to one window; 此代码假定仅将根添加到一个窗口中。 in the unlikely event you're taking the root out of one window and putting it in another during your application life cycle, you would need to remove the listener from the old window. 在极少数情况下,如果您在应用程序生命周期中将根从一个窗口中移出,然后又将其放置在另一个窗口中,则需要从旧窗口中删除侦听器。 If you need this I'll update the code, but it makes it more complex. 如果需要,我将更新代码,但这会使它更加复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM