Quiero manejar eventos de escenario (es decir, ocultar) de mi clase de controlador. Entonces todo lo que tengo que hacer es agregar un oyente a través de
((Stage)myPane.getScene().getWindow()).setOn*whatIwant*(...);
pero el problema es que la inicialización comienza justo después
Parent root = FXMLLoader.load(getClass().getResource("MyGui.fxml"));
y antes
Scene scene = new Scene(root);
stage.setScene(scene);
por tanto .getScene () devuelve nulo.
La única solución que encontré por mí mismo es agregar un oyente a myPane.sceneProperty (), y cuando no se vuelve nulo, obtengo una escena, agrego a su .windowProperty () ¡mi! Maldita sea! manejo del oyente que finalmente recupero el escenario. Y todo termina con la puesta en escena de los oyentes deseados. Creo que hay demasiados oyentes. ¿Es la única forma de resolver mi problema?
load()
método. (Además, el javadoc encendidogetController
parece que debería estar encendidosetController
).Todo lo que necesita es darle
AnchorPane
una identificación, y luego puede obtenerlaStage
.@FXML private AnchorPane ap; Stage stage = (Stage) ap.getScene().getWindow();
Desde aquí, puede agregar en el
Listener
que necesite.Editar: Como indica EarthMind a continuación, no tiene por qué ser el
AnchorPane
elemento; puede ser cualquier elemento que haya definido.fuente
element
puede ser cualquier elemento con unfx:id
en esa ventana:Stage stage = (Stage) element.getScene().getWindow();
. Por ejemplo, si solo tiene unButton
con unfx:id
en sus ventanas, utilícelo para subir al escenario.getScene()
todavía regresanull
.bgimage.sceneProperty().addListener((observableScene, oldScene, newScene) -> { if (oldScene == null && newScene != null) { bgimage.fitWidthProperty().bind(newScene.widthProperty()); ... } });
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) { // scene is set for the first time. Now its the time to listen stage changes. newScene.windowProperty().addListener((observableWindow, oldWindow, newWindow) -> { if (oldWindow == null && newWindow != null) { // stage is set. now is the right time to do whatever we need to the stage in the controller. ((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); ...
fuente
pane
a una escena que ya está adjunta a un escenario, esto no funcionará, ¿verdad? ¿No debería haber una verificación en elsceneProperty
oyente y solo agregar elstageProperty
oyente si la etapa aún es nula? De lo contrario, ¿hago lo que necesito hacer de inmediato?La forma más sencilla de obtener el objeto de escenario en el controlador es:
Agregue un método adicional en la clase de controlador creada por sí mismo como (será un método de establecimiento para configurar el escenario en la clase de controlador),
private Stage myStage; public void setStage(Stage stage) { myStage = stage; }
Obtenga el controlador en el método de inicio y configure el escenario
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyFXML.fxml")); OwnController controller = loader.getController(); controller.setStage(this.stage);
Ahora puedes acceder al escenario en el controlador.
fuente
stage
esta manera.Asigne fx: id o declare variable a / de cualquier nodo: anchorpane, button, etc. Luego agregue el controlador de eventos y dentro de ese controlador de eventos inserte el código dado a continuación:
¡¡Espero que esto funcione para usted!!
fuente
Platform.runLater trabaja para evitar la ejecución hasta que se completa la inicialización. En este caso, quiero actualizar una vista de lista cada vez que cambio el tamaño del ancho de la ventana.
en tu caso
fuente
Puedes quedarte
node.getScene
, si no llamas desdePlatform.runLater
, el resultado es un valor nulo.ejemplo de valor nulo:
ejemplo sin valor nulo:
Platform.runLater(() -> { node.getScene().addEventFilter(KeyEvent.KEY_PRESSED, event -> { //your event }); });
fuente