# 在屏幕之间导航

> 在屏幕之间前进和返回（push/pop）以及向目标屏幕传递数据。

Source: https://crossfly.dev/zh/docs/ui/navigation/navigate-between-screens — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 在屏幕之间导航

## 你将学到什么
- 前进到新屏幕（`show()`）并返回（`hide()`）。
- 向目标屏幕**传递数据**。
- 在哪里构建每个屏幕的 UI。

## 前提条件
理解每个屏幕都是 `Window` 的子类，且 UI 在 `onShow()` 中构建。

## 完整示例（复制、粘贴并运行）
```java
package com.exemplo;

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

/** 可执行的主界面。将 launcher 指向此类（classname）并运行：gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      add(LAY_AUTO, new Label("Lista"));

      Button abrir = new Button("Abrir detalhe do item 42");
      abrir.onAction(c -> new TelaDetalhe(42).show());   // push（前进）——数据通过构造函数传入
      add(LAY_AUTO, abrir);
   }
}

/** 第二个屏幕：通过构造函数接收 id，并用 hide() 返回。 */
class TelaDetalhe extends Window
{
   private final int id;

   public TelaDetalhe(int id) { this.id = id; }   // 数据通过构造函数传入

   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      add(LAY_AUTO, new Label("Detalhe do item " + id));

      Button voltar = new Button("Voltar");
      voltar.onAction(c -> hide());   // pop（返回）
      add(LAY_AUTO, voltar);
   }
}
```
> 下面的片段**仅展示核心部分**（放入 `onShow()` 内的内容）。要运行它们，请放入上面的 `MainWindow` 骨架中。

## 前进（push）和返回（pop）
```java
public class TelaLista extends Window {
   @Override public void onShow() throws Exception {
      super.onShow();
      setLayout(new VerticalLayout());
      Button abrir = new Button("Abrir detalhe");
      abrir.onAction(c -> new TelaDetalhe(42).show());   // push（前进）
      add(LAY_AUTO, abrir);
   }
}

public class TelaDetalhe extends Window {
   private final int id;
   public TelaDetalhe(int id) { this.id = id; }          // 数据通过构造函数传入
   @Override public void onShow() throws Exception {
      super.onShow();
      setLayout(new VerticalLayout());
      add(LAY_AUTO, new Label("Detalhe do item " + id));
      Button voltar = new Button("Voltar");
      voltar.onAction(c -> hide());                       // pop（返回）
      add(LAY_AUTO, voltar);
   }
}
```

## 向下一个屏幕传递数据
不存在"路由参数"。**通过目标 `Window` 的构造函数传递**（如上面的 `id`）。
对于对象，传递其引用：`new TelaCliente(cliente).show();`。

## 在哪里构建 UI
- **`onShow()`**（配合 `super.onShow()`）：此时 `Screen.width/height` 和窗口边界已经有效。
- **不要**在构造函数中构建——边界可能尚未就绪。

## 最佳实践
- 在 **paint 线程之外**加载数据，然后用 `Component.onUI(...)` 返回以填充 UI。
- 在 `onRemove()` 中释放资源（定时器、光标）。

## 常见错误
- 在构造函数中构建 UI（边界无效）或忘记 `super.onShow()`。
- 期望"带命名参数的回退栈"——请通过构造函数传递数据。

## 另见
- [从屏幕返回值](/docs/ui/navigation/returning-results) · [窗口栈](/docs/ui/navigation/the-window-stack)
