# Zona para soltar

> Un área que recibe archivos arrastrados desde el escritorio o el explorador de archivos. Componente de Pyzed para GUIs en Python.

Source: https://albakore.github.io/pyzed/es/library/drop-zone/

:::tip[En pocas palabras]
Un área con borde de rayas donde arrastras archivos desde el escritorio y los sueltas para añadirlos.
:::

`ui.DropZone` se ilumina cuando se arrastran archivos sobre la ventana y los recibe al soltarlos: `on_drop` recibe cada ruta y `on_files` la lista completa. `accept` limita los tipos (`["png", "jpg"]`, `["*.tar.gz"]`, `["folder"]`) y los archivos de otros tipos van a `on_reject`. Con `browse=True` (por defecto) un clic también abre el diálogo de archivos. Si una ventana tiene varias zonas, recibe los archivos la que está bajo el puntero o, si no, la que acepta su tipo.

`ui.DropZone` · Categoría: [Sistema](https://albakore.github.io/pyzed/es/library/#sistema) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#dropzone)

**Código:**

```python
pz.row([
    ui.DropZone(text="Drop images here", hint="PNG or JPG, up to 10 MB", accept=["png", "jpg"],
                on_files=on_files),
    ui.DropZone(icon_name="file-spreadsheet", text="Import a CSV", accept=["csv"], multiple=False,
                show_files=True, files=["~/data/sales-2026.csv"], on_files=on_files),
], spacing=16, width=600)
```

:::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 importar imágenes, documentos o archivos de datos, y adjuntar archivos a un mensaje.
- `show_files=True` lista lo que se soltó, con un botón para quitar cada archivo; `multiple=False` se queda solo con el último.
- Los archivos soltados también llegan a `on_file_drop(path)` de la ventana, para apps que no necesitan una zona.

## Uso

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

class Gallery(pz.App):
    def __init__(self):
        self.images = []

    def view(self):
        return pz.column([
            ui.DropZone(text="Drop photos", accept=["png", "jpg", "webp"],
                        on_files=lambda e: setattr(self, "images", list(e.value))),
            pz.row([pz.image(path, width=96, height=96) for path in self.images], spacing=8),
        ], spacing=12)
```

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

### Estados

```python
ui.DropZone(text="Drop files here", on_files=on_files)
```

```python
ui.DropZone(text="Drop files here", on_files=on_files)
```

```python
ui.DropZone(text="Drop images here", accept=["png", "jpg"], on_files=on_files)
```

```python
ui.DropZone(text="Drop files here", disabled=True, on_files=on_files)
```

### Archivos

```python
ui.DropZone(text="Attach files", show_files=True, files=["~/docs/brief.pdf", "~/img/cover.png"], on_files=on_files)
```

```python
ui.DropZone(icon_name="image", text="Drag a picture", hint="Only by dragging", browse=False, on_files=on_files)
```

## Eventos

Zona para soltar tiene **5 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/).

Es un `pz.Component`, así que también lanza `on_mount` y `on_unmount`, y sus handlers reciben un `pz.Event` cuyo `value` trae el dato.

| Evento | El handler recibe | Cuándo |
| --- | --- | --- |
| `on_drop` | `(event)` | Recibe `event.value`: una ruta soltada (una vez por archivo). |
| `on_files` | `(event)` | Recibe `event.value`: la lista de archivos. |
| `on_reject` | `(event)` | Recibe una ruta que no acepta. |
| `on_enter` | `(event)` | Se arrastran archivos sobre la ventana. |
| `on_leave` | `(event)` | El arrastre salió sin soltar. |

**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 Attach(pz.App):
    def __init__(self):
        self.files = []

    def received(self, event):           # on_files: event.value is every file so far
        self.files = list(event.value)

    def view(self):
        return pz.column([
            ui.DropZone(text="Drop files to attach", on_files=self.received),
            ui.label(f"{len(self.files)} files"),
        ], spacing=8, width=320)
```

**Declarativo:**

```python
from dataclasses import dataclass

@dataclass
class Dropped:
    path: str

class Attach(pz.App):
    files = ()

    def update(self, message):
        match message:
            case Dropped(path):
                self.files = (*self.files, path)

    def view(self):
        # on_drop runs once per file
        return ui.DropZone(accept=["png", "jpg"], on_drop=lambda e: Dropped(e.value))
```

**Funcional:**

```python
from dataclasses import dataclass

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

def view(state, set_state):
    return pz.column([
        ui.DropZone(text="Drop a CSV", accept=["csv"], multiple=False,
                    on_reject=lambda e: set_state(rejected=e.value)),
        ui.label(f"Not a CSV: {state.rejected}" if state.rejected else ""),
    ], spacing=8, width=320)
```

## Consejos

:::tip
Pyzed Design tiene una Zona para soltar en la sección Sistema de la caja de herramientas, junto a los ayudantes no visuales del sistema operativo (información del sistema, lanzador, monitores de red y batería).
:::

## Propiedades y API

### `ui.DropZone`

```python
class DropZone
```

Un componente que recibe archivos arrastrados desde el explorador de archivos del sistema y soltados en la ventana, y abre el diálogo de archivos con un clic. Se ilumina mientras se arrastran archivos sobre la ventana y guarda las rutas soltadas en `files`. El gancho `on_file_drop` de la ventana entrega cada archivo a la zona bajo el puntero, si no a una cuyo `accept` incluya su tipo. Ver la página [Zona para soltar](https://albakore.github.io/pyzed/es/library/drop-zone/).

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `text` | `""` | El texto principal (por defecto: Suelta archivos aquí). |
| `hint` | `""` | La línea de debajo. |
| `icon_name` | `"upload"` | Su icono. |
| `accept` | `()` | Extensiones (`["png", "jpg"]`), patrones (`"*.tar.gz"`) o `"folder"`; vacío acepta todo. |
| `multiple` | `True` | `False` se queda solo con el último archivo. |
| `browse` | `True` | Un clic abre el diálogo de archivos. |
| `show_files` | `False` | Lista los archivos bajo el texto (cada uno con una x). |
| `files` | `()` | Las rutas soltadas. |
| `disabled` | `False` | No recibe nada. |
| `live` | `True` | `False` lo dibuja sin recibir archivos (el lienzo del diseñador). |

Eventos: `on_drop`, `on_files`, `on_reject`, `on_enter`, `on_leave` ([eventos](#eventos)).

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

## Relacionados

- [Selector de archivos](https://albakore.github.io/pyzed/es/library/file-input/): Un campo de ruta con un botón que abre el diálogo de archivos o carpetas del sistema.
- [Tarjeta](https://albakore.github.io/pyzed/es/library/card/): Una superficie con borde, título y acciones opcionales.
