# Cómo abrir y cerrar una pantalla

> Apilar (push) y desapilar (pop) pantallas con show() y hide(), montando la UI en onShow().

Source: https://crossfly.dev/es/docs/cookbook/nav/abrir-tela — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Cómo abrir y cerrar una pantalla

**Propósito.** En CrossFly no hay "rutas": toda pantalla es una `Window` y la navegación es una **pila**. Abrir una pantalla es `show()` (push); volver es `hide()` (pop). La UI de la pantalla debe montarse en `onShow()`.

## APIs usadas
- `Window.show()` — apila la ventana en el `EventsProcessor` y llama a `onShow()` (push). Si se llama fuera del paint thread, agenda y espera.
- `Window.hide()` — desapila la ventana y llama a `onRemove()` (pop). Dispara la transición inversa, si la hay.
- `Window.onShow()` — gancho de ciclo de vida llamado por el framework al apilar; monta la UI aquí. **Siempre llama a `super.onShow()` primero** (recalcula bounds y llama a `onAdd(true)`).
- `EventsProcessor.topWindow()` — retorna la ventana en la cima de la pila (la que recibe eventos).

## Ejemplo completo (copiar, pegar y ejecutar)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      add(new Label("Tela inicial"));
      add(new Button("Abrir detalhe").onAction(e -> new OutraTela().show()));  // push
   }
}

/** Pantalla apilada; el botón "Volver" hace pop (hide) y regresa a MainWindow. */
class OutraTela extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();            // OBLIGATORIO: recalcula bounds y dispara onAdd()
      setLayout(new VerticalLayout());

      add(new Label("Detalhe do pedido"));
      add(new Button("Voltar").onAction(e -> hide()));  // pop: vuelve a la pantalla anterior
   }
}
```

> El fragmento de abajo muestra **solo el núcleo**. Para ejecutarlo, colócalo en el esqueleto `MainWindow` de arriba.

## Fragmento mínimo
```java
// verificado en la fuente: Window.show()/hide()/onShow(); super.onShow() hace updateBounds()+onAdd(true)
public class MinhaTela extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();            // OBLIGATORIO: recalcula bounds y dispara onAdd()
      setLayout(new GridLayout());

      add(new Label("Detalhe do pedido"));
      add(new Button("Voltar").onAction(e -> hide()));  // pop: vuelve a la pantalla anterior
   }
}

// En cualquier lugar (ej.: en el onAction de un botón de la pantalla anterior):
new MinhaTela().show();          // push: apila y muestra
```

Reglas que evitan bugs:

- **Nunca montes la UI en el constructor** de forma que dependa del tamaño de pantalla — `Screen.width/height` solo está estabilizado cuando `onShow()` se ejecuta. Usa `onShow()`.
- `hide()` cierra **la propia** ventana. Para cerrar la ventana de la cima desde fuera, usa `EventsProcessor.topWindow().hide()`.
- `show()` es seguro fuera del paint thread: reencamina al thread de pintura y espera.

## Profundiza
- [Navegar entre pantallas](/docs/ui/navigation/navigate-between-screens) · [La pila de ventanas](/docs/ui/navigation/the-window-stack)
- Receta hermana: [Recibir resultado de una pantalla](/docs/cookbook/nav/receber-resultado)
