# Elección

> Un mensaje con tus propios botones. 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/choice/

:::tip[En pocas palabras]
Una pregunta con varias respuestas posibles, cada una un botón.
:::

Un mensaje con tus propios botones: `options` son pares `(etiqueta, on_press)` y el último es el principal.

`ui.choice` · Categoría: [Diálogos](https://albakore.github.io/pyzed/es/library/#diálogos) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#choice)

**Código:**

```python
ui.dialog_layer(main_view(), ui.choice(
    "notes.py already exists in this folder.",
    [("Keep both", on_keep), ("Skip", on_skip), ("Replace", on_replace)],
    on_cancel, title="File exists", width=420,
))
```

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

- Cuando una pregunta tiene más de dos respuestas (Conservar ambos / Reemplazar / Omitir).

## Uso

```python
from pyzed import ui

ui.dialog_layer(main_view(), ui.choice(
    "notes.py already exists in this folder.",
    [("Keep both", on_keep), ("Skip", on_skip), ("Replace", on_replace)],
    on_cancel, title="File exists", width=420,
))
```

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

### Opciones

```python
ui.choice("Open the project in…", [("This window", on_here), ("New window", on_new)],
          on_cancel, width=360)
```

```python
ui.choice("notes.py already exists.", [("Keep both", on_keep), ("Skip", on_skip),
          ("Replace", on_replace)], on_cancel, title="File exists", width=400)
```

## Eventos

Elección tiene **1 evento 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 | El handler recibe | Cuándo |
| --- | --- | --- |
| `on_cancel` | `()` | El icono de cerrar. |

**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 Copy(pz.App):
    def __init__(self):
        self.asking, self.answer = True, None

    def answer_with(self, what):
        self.asking, self.answer = False, what

    def view(self):
        dialog = ui.choice("notes.py already exists in this folder.",
                           [("Keep both", lambda: self.answer_with("both")),   # one handler per option
                            ("Replace", lambda: self.answer_with("replace"))],
                           lambda: setattr(self, "asking", False),             # on_cancel: the ✕
                           title="File exists")
        return ui.dialog_layer(main_view(), dialog if self.asking else None)
```

**Declarativo:**

```python
from dataclasses import dataclass

@dataclass
class Answer:
    what: str

class Copy(pz.App):
    asking = True

    def update(self, message):
        match message:
            case Answer(what):
                self.asking = False
                print("chose", what)
            case "cancel":
                self.asking = False

    def view(self):
        dialog = ui.choice("notes.py already exists.", [("Keep both", Answer("both")),
                                                        ("Replace", Answer("replace"))], "cancel")
        return ui.dialog_layer(main_view(), dialog if self.asking else None)
```

**Funcional:**

```python
from dataclasses import dataclass

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

def view(state, set_state):
    if state.answer:
        return ui.label(f"You chose: {state.answer}")
    return ui.dialog_layer(main_view(), ui.choice(
        "notes.py already exists.",
        [(label, lambda a=answer: set_state(answer=a)) for label, answer in (("Keep both", "both"),
                                                                            ("Replace", "replace"))],
        lambda: set_state(answer="cancel")))
```

## Propiedades y API

### `ui.choice`

```python
choice(message, options, on_cancel, *, title=None, width=440, theme=None)
```

Un mensaje con tus propios botones.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `message` | *obligatorio* | Cualquier valor de Python, o un callable. |
| `options` | *obligatorio* | Pares `(texto, on_press)`; el último es el botón principal. |
| `title` | `None` | Título. |
| `width` | `440` | Ancho: píxeles, `"fill"`, `"shrink"` o `"fill:N"` (proporción). |
| `theme` | `None` | Tema a usar en lugar del actual (`pyzed.theme.current()`). |

Eventos: `on_cancel` ([eventos](#eventos)).

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

## Relacionados

- [Confirmación](https://albakore.github.io/pyzed/es/library/confirm/): Una pregunta de sí o no, en rojo para acciones destructivas.
- [Cambios sin guardar](https://albakore.github.io/pyzed/es/library/unsaved-changes/): “¿Guardar los cambios antes de cerrar?”
