所以我试图用这样的代码从控制器处理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();
}
}
但是我所得到的只是无休止的循环和程序崩溃。
下面的代码也不起作用,它返回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");
}
});
}
实现WindowEvent接口根本行不通,不知道为什么。
那么,我该如何处理此事件?以及为什么我有NullPointerException?在文档中说
initialize()
仅在根窗格完全处理后调用。 最佳答案
当执行initialize()方法时,根窗格已完全构建,但未添加到场景或窗口中。 (initialize()方法是FXMLLoader的load()方法执行的一部分;要检查调用该代码的代码,您会看到将根添加到场景中,然后将其放置在窗口中。)因此,在执行intialize()期间,root.getScene()将返回null。
您可以使用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);
}
}
});
此代码假定仅将根添加到一个窗口中。在极少数情况下,如果您在应用程序生命周期中将根从一个窗口中移出,然后又将其放置在另一个窗口中,则需要从旧窗口中删除侦听器。如果需要,我将更新代码,但这会使它更加复杂。