# Disposición anclada

> Posiciones libres como en un diseñador de formularios, con anclas que siguen al redimensionar. Componente de Pyzed para GUIs en Python.

Source: https://albakore.github.io/pyzed/es/library/anchor-layout/

:::tip[En pocas palabras]
Coloca las cosas justo donde las pones y dice a qué esquina se pega cada una cuando la ventana crece.
:::

Coloca los hijos en posiciones exactas, como un diseñador visual de formularios, y dice cómo sigue cada uno un cambio de tamaño: `pz.anchor(child, x=, y=, width=, height=, anchor=)` mantiene la distancia a los bordes a los que está anclado, se estira entre bordes opuestos y si no se queda centrado. Presets como `"top_right"`, `"bottom_wide"`, `"center"` o `"full"` cubren los casos habituales. `pyzed.anchors.place` es la cuenta que hay detrás, para tus propias disposiciones.

`pz.anchor_layout` · Categoría: [Disposición](https://albakore.github.io/pyzed/es/library/#disposición) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/widgets/#anchor_layout)

**Código:**

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([
    pz.anchor(ui.heading("Report", level=3), x=16, y=12, width=200, height=28, anchor="top_left"),
    pz.anchor(ui.icon_button("x", on_close), x=356, y=12, width=28, height=28, anchor="top_right"),
    pz.anchor(ui.input("", on_input, placeholder="Search…"), x=16, y=56, width=368, height=30,
              anchor="top_wide"),
    pz.anchor(ui.button("Close", on_close, variant="solid"), x=284, y=172, width=100, height=30,
              anchor="bottom_right"),
], design=(400, 216)), width=400, height=216, bg=t.panel, border_color=t.border, border_width=1, radius=8)
```

:::note[Nuevo]
Este componente se añadió hace poco. Cuéntanos qué tal te funciona en el [gestor de incidencias](https://github.com/albakore/pyzed/issues).
:::

## Cuándo usarlo

- Para formularios dibujados en Pyzed Design (es lo que genera la vista de Formulario) o traídos de Visual Basic, Qt Designer o WinForms.
- Para HUDs de juegos y capas en las que las cosas se pegan a las esquinas.
- Para formularios que crecen y encogen con la ventana, mejor `row`, `column` y `grid`.

## Uso

```python
import pyzed as pz
from pyzed import ui

class Report(pz.App):
    def view(self):
        return pz.anchor_layout([
            pz.anchor(ui.heading("Report"), x=16, y=12, width=368, height=28, anchor="top_wide"),
            pz.anchor(self.table(), x=16, y=48, width=368, height=196, anchor="full"),
            pz.anchor(ui.button("Close", self.close), x=284, y=252, width=100, height=32,
                      anchor="bottom_right"),
        ], design=(400, 300))
```

## Variantes

:::note[Sobre estas capturas]
Cada captura la graba pyzed mismo, fuera de pantalla a 2x, en One Dark o One Light según el tema de este sitio, y recortada al componente para que se vea a su tamaño real. El puntero pasa por encima, pulsa o escribe en él; un componente que no reacciona al puntero recorre algunos temas. Con movimiento reducido ves el primer fotograma. Abre **Código** bajo una captura para ver el fragmento que la dibuja; los nombres libres como `on_save` son tus propios callbacks.
:::

### Presets

Cada disposición se diseñó a 110 × 44 y se dibuja a 260 × 110: la insignia mantiene su distancia a los bordes a los que está anclada.

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(ui.badge("top_left"), x=10, y=10, width=90, height=24,
                                         anchor="top_left")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(ui.badge("top_right"), x=10, y=10, width=90, height=24,
                                         anchor="top_right")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(ui.badge("bottom_left"), x=10, y=10, width=90, height=24,
                                         anchor="bottom_left")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(ui.badge("bottom_right"), x=10, y=10, width=90, height=24,
                                         anchor="bottom_right")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(ui.badge("center"), x=10, y=10, width=90, height=24,
                                         anchor="center")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

### Estirar

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(pz.container(width="fill", height="fill", bg=t.accent, radius=4),
                                         x=10, y=10, width=90, height=24, anchor="top_wide")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(pz.container(width="fill", height="fill", bg=t.accent, radius=4),
                                         x=10, y=10, width=90, height=24, anchor="bottom_wide")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(pz.container(width="fill", height="fill", bg=t.accent, radius=4),
                                         x=10, y=10, width=90, height=24, anchor="left_tall")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(pz.container(width="fill", height="fill", bg=t.accent, radius=4),
                                         x=10, y=10, width=90, height=24, anchor="center_wide")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

```python
t = pz.theme.current()
pz.container(pz.anchor_layout([pz.anchor(pz.container(width="fill", height="fill", bg=t.accent, radius=4),
                                         x=10, y=10, width=90, height=24, anchor="full")], design=(110, 44)),
             width=260, height=110, border_color=t.border, border_width=1, radius=8)
```

## Eventos

Disposición anclada no tiene eventos propios: muestra lo que le das. Como todo widget, también tiene los **18 eventos comunes** (`click`, `double_click`, `right_click`, `mouse_enter`, `drag`, `key_down`, `resize`…), que se conectan con `.on(...)`: mira [Eventos](https://albakore.github.io/pyzed/es/guides/events/) y [Eventos de cada componente](https://albakore.github.io/pyzed/es/library/events/).

## Consejos

:::tip
`design` es el tamaño en el que se midieron las posiciones; cuando la disposición tiene más o menos espacio, cada hijo se mueve o se estira desde ahí. Pruébalo en vivo: arrastra la esquina de un formulario en Pyzed Design.
:::

## Propiedades y API

### `pz.anchor_layout`

```python
anchor_layout(children, *, design=None, width='fill', height='fill')
```

Coloca libremente hijos hechos con `pz.anchor`, como un formulario diseñado: al cambiar de tamaño, cada hijo mantiene su distancia a los bordes a los que está anclado, se estira entre bordes opuestos y se queda centrado en los demás casos. Los últimos hijos se dibujan encima. Ver [Disposiciones ancladas](https://albakore.github.io/pyzed/es/guides/layout/#disposiciones-ancladas).

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `children` | *obligatorio* | Hijos hechos con `pz.anchor(...)` (`None` se ignora). |
| `design` | `None` | `(ancho, alto)` en el que se colocaron los hijos; por defecto, el más pequeño que los contiene. |
| `width` | `"fill"` | Ancho. |
| `height` | `"fill"` | Alto. |

[Referencia completa →](https://albakore.github.io/pyzed/es/reference/widgets/#anchor_layout)

### `pz.anchor`

```python
anchor(
    content,
    *,
    x=0,
    y=0,
    width=100,
    height=28,
    anchor='top_left',
    min_width=0,
    min_height=0,
    max_width=0,
    max_height=0,
    pivot=(0.5, 0.5),
    rotate=0,
)
```

Coloca un hijo de `pz.anchor_layout` en `x`, `y` con `width` y `height` (en el tamaño de diseño de la disposición) y dice cómo sigue a un cambio de tamaño.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `content` | *obligatorio* | El widget. |
| `x` | `0` | Borde izquierdo en el tamaño de diseño. |
| `y` | `0` | Borde superior en el tamaño de diseño. |
| `width` | `100` | Ancho en el tamaño de diseño. |
| `height` | `28` | Alto en el tamaño de diseño. |
| `anchor` | `"top_left"` | Un preset de `pyzed.anchors.PRESETS` (`"top_right"`, `"bottom_wide"`, `"center"`, `"full"`...), palabras (`"left right bottom"`) o una tupla de bordes. |
| `min_width` | `0` | Ancho mínimo al estirarse (`0`: sin límite). |
| `min_height` | `0` | Alto mínimo al estirarse. |
| `max_width` | `0` | Ancho máximo al estirarse (`0`: sin límite). |
| `max_height` | `0` | Alto máximo al estirarse. |
| `pivot` | `(0.5, 0.5)` | `(x, y)` de `0` a `1`: el punto que queda fijo cuando un límite lo frena, y alrededor del que gira `rotate`. |
| `rotate` | `0` | Grados en sentido horario. |

[Referencia completa →](https://albakore.github.io/pyzed/es/reference/widgets/#anchor)

### `pz.anchors.place`

```python
place(
    rect,
    anchor,
    design,
    actual,
    *,
    min_size=(0, 0),
    max_size=(0, 0),
    pivot=(0.5, 0.5),
)
```

Dónde va una caja diseñada en un padre de tamaño `design` dentro de un padre de tamaño `actual`, siguiendo su anclaje, con límites de tamaño y un pivote. La cuenta detrás de `pz.anchor_layout` y de los formularios diseñados.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `rect` | *obligatorio* | `(x, y, ancho, alto)` en el tamaño de diseño. |
| `anchor` | *obligatorio* | Un preset, palabras o bordes. |
| `design` | *obligatorio* | El tamaño de diseño del padre. |
| `actual` | *obligatorio* | El tamaño actual del padre. |
| `min_size` | `(0, 0)` | Límites inferiores `(ancho, alto)` (`0`: ninguno). |
| `max_size` | `(0, 0)` | Límites superiores `(ancho, alto)` (`0`: ninguno). |
| `pivot` | `(0.5, 0.5)` | El punto que queda fijo cuando un límite frena el estiramiento. |

[Referencia completa →](https://albakore.github.io/pyzed/es/reference/widgets/#place)

## Relacionados

- [Pila](https://albakore.github.io/pyzed/es/library/stack/): Superpone los hijos; `pin` coloca uno en x, y.
- [Cuadrícula](https://albakore.github.io/pyzed/es/library/grid/): Columnas iguales, o pistas como en CSS con expansión.
- [Contenedor](https://albakore.github.io/pyzed/es/library/container/): Tamaño, relleno, alineación, fondo, borde y sombra para un hijo.
