Sé que no es la respuesta que desea, pero en mi opinión, las soluciones propuestas no son buenas (y a su manera sí lo es). ¿Por qué? Porque dependen del estado de la aplicación. En JavaFX, un control, una escena y un escenario no dependen el uno del otro. Esto significa que un control puede vivir sin ser agregado a una escena y una escena puede existir sin estar adjunta a un escenario. Y luego, en un instante de tiempo t1, el control se puede adjuntar a una escena y en el instante t2, esa escena se puede agregar a un escenario (y eso explica por qué son propiedades observables entre sí).
Entonces, el enfoque que sugiere obtener la referencia del controlador e invocar un método, pasando la etapa, agrega un estado a su aplicación. Esto significa que debe invocar ese método en el momento adecuado, justo después de que se crea la etapa. En otras palabras, debe seguir una orden ahora: 1- Crear la etapa 2- Pasar esta etapa creada al controlador a través de un método.
No puede (o no debe) cambiar este orden en este enfoque. Entonces perdiste la apatridia. Y en el software, en general, el estado es malo. Idealmente, los métodos no deberían requerir ningún orden de llamada.
Entonces, ¿cuál es la solución correcta? Hay dos alternativas:
1- Tu enfoque, en las propiedades de escucha del controlador para subir al escenario. Creo que este es el enfoque correcto. Me gusta esto:
pane.sceneProperty().addListener((observableScene, oldScene, newScene) -> {
if (oldScene == null && newScene != null) {
newScene.windowProperty().addListener((observableWindow, oldWindow, newWindow) -> {
if (oldWindow == null && newWindow != null) {
((Stage) newWindow).maximizedProperty().addListener((a, b, c) -> {
if (c) {
System.out.println("I am maximized!");
}
});
}
});
}
});
2- Haces lo que tienes que hacer donde creas el Stage
(y eso no es lo que quieres):
Stage stage = new Stage();
stage.maximizedProperty().addListener((a, b, c) -> {
if (c) {
System.out.println("I am maximized!");
}
});
stage.setScene(someScene);
...