# 窗口与导航

> Window、onShow()、LIFO 栈(show/hide)、通过构造函数传递数据以及返回值。

Source: https://crossfly.dev/zh/docs/learn/windows-and-navigation — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 2. 窗口与导航

> **你将学到:** 界面单元(`Window`)、在哪里搭建 UI 以及基于栈的导航模型。**前置条件:** [全景](/docs/learn/big-picture)。

## 完整示例(复制、粘贴、运行)
两个界面通过栈导航(push/hide),数据经由构造函数传递。`MainWindow` 是列表;`TelaDetalhe` 是详情。可直接编译运行。
```java
package com.exemplo;

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

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

      add(LAY_AUTO, new Label("Minhas tarefas"));

      Button abrir = new Button("Abrir tarefa 42");
      abrir.onAction(c -> new TelaDetalhe(42).show());   // push：将详情入栈
      add(LAY_AUTO, abrir);
   }
}

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("Tarefa " + id));

      Button voltar = new Button("Voltar");
      voltar.onAction(c -> hide());                       // pop：出栈，返回列表
      add(LAY_AUTO, voltar);
   }
}
```
> 下面的片段只展示**核心部分**(放在 `onShow()` 里的内容)。要运行,请把它们放进上面的 `MainWindow` 骨架里。

## `Window` 与 `onShow()`
每个界面都是 `Window`(它本身是一个 `Component`)的子类。在 **`onShow()`** 中搭建 UI —— 并调用 `super.onShow()` —— 此时 bounds 已经有效(切勿在构造函数里搭建)。

## 导航栈(LIFO)
`show()` **入栈**(push)一个窗口;`hide()` **出栈**(pop)。栈顶的窗口接收输入。
```java
public class TelaLista extends Window {
   @Override public void onShow() throws Exception {
      super.onShow();
      setLayout(new VerticalLayout());
      Button abrir = new Button("Abrir tarefa 42");
      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("Tarefa " + id));
      Button voltar = new Button("Voltar");
      voltar.onAction(c -> hide());                       // pop
      add(LAY_AUTO, voltar);
   }
}
```

## 传递数据与返回值
- **携带数据跳转到某个界面:** 通过**构造函数**(`new TelaDetalhe(42).show()`)。
- **返回一个值:** [picker](/docs/ui/widgets/picker) 使用 `show(onAnswer)`;普通界面使用**构造函数传入的回调**;对话框(`Alert`)通过 `buttonAction` 响应(见[返回值](/docs/ui/navigation/returning-results))。

## 本步骤所构建的
主线应用的**两个界面**骨架:**列表 → 详情**,可相互导航。

## 回顾
界面 = `Window`;UI 在 `onShow()`+`super.onShow()` 中;`show()`/`hide()` = push/pop;数据通过构造函数传递。

## 下一步
→ [组件化思维](/docs/learn/thinking-in-components)

## 另见
- [导航(ui)](/docs/ui/navigation) · 概念:[生命周期](/docs/concepts/lifecycle)
