# Select

> Un desplegable para elegir una opción. Un componente nativo de Pyzed para GUIs de escritorio en Python, con vista previa, ejemplos y su API.

Source: https://albakore.github.io/pyzed/es/library/select/

:::tip[En pocas palabras]
Una caja que abre una lista para que elijas una opción.
:::

Un desplegable con el estilo del tema. Las opciones se muestran con `str()`, así que valen cadenas, enums o dataclasses, y `on_select` recibe el objeto elegido.

`ui.select` · Categoría: [Formularios](https://albakore.github.io/pyzed/es/library/#formularios) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#select)

**Código:**

```python
pz.row([
    ui.select(["Python", "Rust", "TypeScript"], "Rust", on_select, width=180),
    ui.select(["UTF-8", "Latin-1"], None, on_select, placeholder="Encoding…", width=180),
], spacing=12)
```

## Cuándo usarlo

- Para elegir una entre muchas opciones cuando no caben todas (idioma, tema, codificación).
- Con dos a cinco opciones cortas, [Segmentado](https://albakore.github.io/pyzed/es/library/segmented/) o un [Grupo de radios](https://albakore.github.io/pyzed/es/library/radio-group/) las muestran de un vistazo.

## Uso

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

class Settings(pz.App):
    def __init__(self):
        self.language = "Python"

    def view(self):
        return ui.select(["Python", "Rust", "TypeScript"], self.language,
                         lambda value: setattr(self, "language", value), width=180)
```

## 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.
:::

### Estado

```python
ui.select(["Python", "Rust", "TypeScript"], "Rust", on_select, width=200)
```

```python
ui.select(["UTF-8", "Latin-1"], None, on_select, placeholder="Encoding…", width=200)
```

```python
ui.select(["One Dark"], "One Dark", width=200)
```

### Tamaño

```python
ui.select(["Python", "Rust"], "Python", on_select, size="sm", width=200)
```

```python
ui.select(["Python", "Rust"], "Python", on_select, size="md", width=200)
```

```python
ui.select(["Python", "Rust"], "Python", on_select, size="lg", width=200)
```

### Estados y eventos

`on_open` y `on_close` se ejecutan al abrir y cerrar el menú.

```python
ui.select(["One Dark"], "One Dark", on_select, disabled=True, width=200)
```

```python
ui.select(["UTF-8", "Latin-1"], None, on_select, placeholder="Encoding…", invalid=True, width=200)
```

### Widget base

El widget `pz.*` de debajo: sin tema, todos los colores y tamaños son tuyos.

```python
pz.pick_list(["Small", "Medium", "Large"], "Medium", on_select, width=200,
             bg="#2b2140", color="#e9d5ff", border_color="#c678dd", radius=8)
```

## Eventos

Select tiene **3 eventos propios**, en la tabla de abajo. 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/).

| Evento | De | El handler recibe | Cuándo |
| --- | --- | --- | --- |
| `on_select` | `ui.select`, `pz.pick_list` | `(item)` | Callable que recibe el elemento elegido. |
| `on_open` | `ui.select`, `pz.pick_list` | `()` | Se envía al abrir el menú. |
| `on_close` | `ui.select`, `pz.pick_list` | `()` | Se envía al cerrar el menú. |

**El handler recibe** es lo que Pyzed le pasa a tu función: `()` es nada. Cualquier handler también puede ser un mensaje (un valor que no se puede llamar), que va a `update()`.

### Manejar los eventos

Los mismos eventos escritos de tres formas. **Imperativa**: métodos de la app que cambian `self`. **Declarativa**: los handlers producen mensajes y un único `update()` decide. **Funcional**: una función pura dibuja un estado inmutable y pide cambios con `set_state(...)`. Mira [Imperativo, declarativo y funcional](https://albakore.github.io/pyzed/es/guides/code-styles/).

**Imperativo:**

```python
class Settings(pz.App):
    def __init__(self):
        self.language = "Python"
        self.open = False

    def view(self):
        return pz.column([
            ui.select(["Python", "Rust", "TypeScript"], self.language,
                      lambda value: setattr(self, "language", value),       # on_select: the option
                      on_open=lambda: setattr(self, "open", True),
                      on_close=lambda: setattr(self, "open", False), width=180),
            ui.muted("Choosing…" if self.open else f"Language: {self.language}"),
        ], spacing=8)
```

**Declarativo:**

```python
from dataclasses import dataclass

@dataclass
class Language:
    name: str

class Settings(pz.App):
    language = "Python"

    def update(self, message):
        match message:
            case Language(name):
                self.language = name

    def view(self):
        return ui.select(["Python", "Rust", "TypeScript"], self.language, Language, width=180)
```

**Funcional:**

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class State:
    language: str = "Python"

def view(state, set_state):
    return ui.select(["Python", "Rust", "TypeScript"], state.language,
                     lambda value: set_state(language=value), width=180)
```

## Consejos

:::tip
Toma el foco del teclado como un campo de texto (con un clic o Tab) y lo mantiene después de elegir: entonces ↓/↑ eligen la opción siguiente o la anterior sin abrir el menú, Inicio/Fin la primera y la última, y al escribir salta a la opción que empieza por esas letras. Enter, Espacio, Alt+↓ o F4 abren el menú; ahí ↑/↓ se mueven, Enter elige y Esc lo cierra. Pasa `id=` para enfocarlo con `pz.Command.focus(id)`.
:::

## Propiedades y API

### `ui.select`

```python
select(
    options,
    selected=None,
    on_select=None,
    *,
    placeholder='Select…',
    width=None,
    size='md',
    disabled=False,
    invalid=False,
    on_open=None,
    on_close=None,
    id=None,
    theme=None,
)
```

Un desplegable con el estilo del tema. Las opciones se muestran con `str()`, así que sirven textos, enums, dataclasses o modelos de base de datos; `on_select` recibe el objeto elegido, no su texto.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `options` | *obligatorio* | Lista de opciones. |
| `selected` | `None` | Opción actual. |
| `placeholder` | `"Select…"` | Texto de ayuda cuando está vacío. |
| `width` | `None` | Ancho: píxeles, `"fill"`, `"shrink"` o `"fill:N"` (proporción). |
| `size` | `"md"` | `"sm"`, `"md"` o `"lg"`. |
| `disabled` | `False` | Lo atenúa. |
| `invalid` | `False` | Pinta el borde con el color de error. |
| `id` | `None` | Identificador estable para enfocarlo o desplazarlo con un `Command`. |
| `theme` | `None` | Tema a usar en lugar del actual (`pyzed.theme.current()`). |

Eventos: `on_select`, `on_open`, `on_close` ([eventos](#eventos)).

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

### `pz.pick_list`

```python
pick_list(
    options,
    selected=None,
    on_select=None,
    *,
    on_open=None,
    on_close=None,
    placeholder=None,
    width=None,
    padding=None,
    text_size=None,
    font=None,
    handle=None,
    handle_size=12.0,
    menu_height=None,
    bg=None,
    color=None,
    placeholder_color=None,
    handle_color=None,
    border_color=None,
    hover_border_color=None,
    radius=None,
    menu_bg=None,
    menu_color=None,
    menu_border_color=None,
    selected_bg=None,
    selected_color=None,
    focus_border_color=None,
    id=None,
)
```

Un desplegable para elegir una de `options`. `on_select(opción)` recibe la elegida. Para el desplegable con tema usa `ui.select`. Toma el foco del teclado como un campo de texto (un clic, Tab o `Command.focus(id)`) y lo mantiene después de elegir: ↑/↓ eligen la opción anterior o la siguiente sin abrirlo, Inicio/Fin la primera y la última y al escribir salta a una opción; Enter, Espacio, Alt+↓ o F4 abren el menú, donde ↑/↓ se mueven, Enter elige y Esc cierra.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `options` | *obligatorio* | Lista de opciones. |
| `selected` | `None` | Opción actual. |
| `placeholder` | `None` | Texto de ayuda cuando está vacío. |
| `width` | `None` | Ancho: píxeles, `"fill"`, `"shrink"` o `"fill:N"` (proporción). |
| `padding` | `None` | Relleno interior: `8`, `(vertical, horizontal)` o `(arriba, derecha, abajo, izquierda)`. |
| `text_size` | `None` | Tamaño del texto. |
| `font` | `None` | Familia de la fuente. |
| `handle` | `None` | Carácter del icono de la flecha. |
| `handle_size` | `12.0` | Tamaño de la flecha. |
| `menu_height` | `None` | Alto máximo del menú. |
| `bg` | `None` | Color de fondo (`"#rrggbb[aa]"`, `(r, g, b[, a])` o `"transparent"`). |
| `color` | `None` | Color del texto o del icono. |
| `placeholder_color` | `None` | Color del placeholder. |
| `handle_color` | `None` | Color de la flecha. |
| `border_color` | `None` | Color del borde. |
| `hover_border_color` | `None` | Color del borde al pasar el ratón. |
| `radius` | `None` | Radio de las esquinas: un número o `(sup_izq, sup_der, inf_der, inf_izq)`. |
| `menu_bg` | `None` | Fondo del menú. |
| `menu_color` | `None` | Texto del menú. |
| `menu_border_color` | `None` | Borde del menú. |
| `selected_bg` | `None` | Fondo de la opción resaltada. |
| `selected_color` | `None` | Texto de la opción resaltada. |
| `focus_border_color` | `None` | Color del borde mientras tiene el foco del teclado. |
| `id` | `None` | Identificador estable para enfocarlo o desplazarlo con un `Command`. |

Eventos: `on_select`, `on_open`, `on_close` ([eventos](#eventos)).

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

## Relacionados

- [Segmentado](https://albakore.github.io/pyzed/es/library/segmented/): Un grupo de botones de texto excluyentes.
- [Grupo de radios](https://albakore.github.io/pyzed/es/library/radio-group/): Opciones excluyentes como botones de radio.
- [Buscador](https://albakore.github.io/pyzed/es/library/picker/): Una lista con búsqueda en una superficie flotante, con coincidencia difusa.
