# Label

> 用于显示文本（带自动换行）和/或只读图标的非交互式组件。

Source: https://crossfly.dev/zh/docs/ui/widgets/label — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Label

`Label` 是最常用的**显示**组件：显示只读文本，支持自动换行（word-wrap）、多行（通过 `\n` 显式或自动换行）以及左侧和/或右侧的可选图标。它不响应点击 —— 若需操作请使用 [`Button`](/docs/ui/widgets/button)；若需可编辑文本请使用 [`TextField`](/docs/ui/widgets/textfield)/[`TextArea`](/docs/ui/widgets/textarea)。

渲染被委托给活跃的 `Design`：`Label` 仅在 `onLayout()` 中计算坐标，并暴露供 `Design` 使用的公共字段（字体、颜色和边框来自 `LabelStyle`）。

> 🟢 · **包：** `dev.crossfly.ui` · **继承：** `Component` · **样式：** `LabelStyle`

## 何时使用
- 标题、副标题、说明文字和只读值。
- 带左侧或右侧信息图标的文本。
- 需要换成多行的文本块。

## 何时不要使用
- 可编辑文本 → 使用 [`TextField`](/docs/ui/widgets/textfield) / [`TextArea`](/docs/ui/widgets/textarea)。
- 可点按 / 可点击的元素 → 使用 [`Button`](/docs/ui/widgets/button)（`Label` 不响应点击）。

## 外观
文本在内部区域（应用 `ingap` 之后）内渲染，水平和垂直对齐依据 `LabelStyle.textAlignH`/`textAlignV`。左侧图标贴紧左内边界；右侧图标贴紧右内边界；文本占据两者之间的空间。

``

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

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

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

      // 将由按钮更新的只读 Label
      Label saida = new Label("Toque no botão abaixo");
      add(LAY_AUTO, saida);

      // 改变 Label 文字的按钮（Label.setText 为链式调用并返回 Label）
      Button ola = new Button("Dizer olá").onAction(c -> saida.setText("Olá, mundo!"));
      add(LAY_AUTO, ola);
   }
}
```

> 下面的片段只展示**核心部分**（放入 `onShow()` 内的内容）。要运行它们，请将其放入上面的 `MainWindow` 骨架中。

## 基本用法
```java
Label hello = new Label("Olá, mundo!");
container.add(LAY_AUTO, hello);
```

## 构造函数
| 构造函数 | 描述 |
|---|---|
| `Label()` | 空 label（`text = ""`） |
| `Label(String text)` | 文本 label |
| `Label(Icon onlIcon)` | 仅图标的 label（图标在左侧） |

## 属性与自定义
| 属性 / 方法 | 类型 | 默认值 | 作用 |
|---|---|---|---|
| `setText(String)` | `Label`（链式） | — | 更换文本；**仅当**值发生变化时才使布局失效 |
| `leftIcon(Icon)` | `Label`（链式） | `null` | 定义文本左侧的图标 |
| `rightIcon(Icon)` | `Label`（链式） | `null` | 定义文本右侧的图标 |
| `text` | `String`（公共字段） | `""` | 当前内容（可包含 `\n`） |
| 样式 `.textAlign(Position, Position)` | `Position` | 主题 | 文本的水平/垂直对齐 |
| 样式 `.backColor(int)` / `.borderColor(int)` | ARGB | 主题 | 背景/边框（使用 `0` 表示透明） |
| `getAutoWidth()` / `getAutoHeight(int)` | `int` | — | 首选尺寸（供布局使用） |
| `Label.wordWrap(String, Font, int)` *(static)* | `String[]` | — | 按宽度换行的工具方法 |

> `setText(String)` 返回 `Label`（用于链式调用），**而非** `void` —— 因此尽管 `Label` 暴露了 `setText`/`text`，它并不声明 `implements TextComponent`。

## 回调与事件
无。`Label` 是非交互式的 —— 不触发 `onAction`，也不触发点击事件。

## 状态
没有交互状态（没有 `pressed`/`focused`）。视觉仅随所应用的样式变化，或通过 `setEnabled(false)` 变化（禁用外观，依据 `Design`）。

### 左侧图标与无背景的副标题
```java
// 左侧带图标的 Label（Material "info"）
Label info = new Label("Informação")
   .leftIcon(new MaterialIcon(""));
container.add(LAY_AUTO, info);

// 左对齐副标题，无背景/边框
Label sub = new Label("Lista:").style(
   Styles.theme().label(LabelRole.SUBTITLE)
      .backColor(0)
      .borderColor(0)
      .textAlign(Position.START, Position.CENTER));
container.add(LAY_AUTO, sub);
```

### 多行（word-wrap + 显式 `\n`）
```java
// 显式换行
Label endereco = new Label("Rua das Flores, 123\nCentro\n01000-000");

// 自动换行：给 Label 设置宽度 (LAY_FILL) 才会换行
Label paragrafo = new Label(
   "Este texto longo quebra automaticamente em várias linhas quando "
 + "a largura disponível é menor que a largura do texto.");
container.add(LAY_FILL, paragrafo);
```

## 最佳实践
- 对于 word-wrap，请确保布局为 `Label` 提供**宽度**（例如在 `VerticalLayout` 中 `add(LAY_FILL, label)`）。若无已知宽度，在高度计算中只会统计显式的 `\n`。
- 使用主题角色（`LabelRole.TITLE`/`SUBTITLE`/…）而不是硬编码字体/颜色。

## 常见错误
- **期望在未定义宽度时进行 word-wrap：** 如果在高度计算中宽度为 `0`/未知，则只统计显式的 `\n` 换行。请为 `Label` 提供宽度。
- **混淆 `setText` 与 `TextComponent.setText` 契约：** 这里 `setText` 返回 `Label`，而非 `void`；`Label` 并不实现 `TextComponent`。

## 另请参阅
- 领域指南：[`ui/`](/docs/ui) · 食谱：[`cookbook/`](/docs/cookbook)
- 概念（"一切皆 `Component`"）：[`concepts/`](/docs/concepts)
- 相关组件：[`Button`](/docs/ui/widgets/button) · [`TextField`](/docs/ui/widgets/textfield) · [`ImageView`](/docs/ui/widgets/imageview)
