Servicios
Los servicios son las partes de una app que lanzan eventos pero no dibujan nada: pz.Timer, pz.Shortcut,
pz.FileWatcher, pz.Process, pz.Worker, pz.HttpRequest, pz.Clipboard, pz.Settings, pz.FileDialog,
pz.Notification y pz.TrayIcon. Son los mismos objetos que los componentes no visuales
de Pyzed Design, y funcionan en un pz.App, en un formulario o en un script sin ninguna ventana.
from pathlib import Path
import pyzed as pzfrom pyzed import ui
class Inbox(pz.App): def __init__(self): self.files = sorted(p.name for p in Path("inbox").glob("*")) self.watcher = pz.FileWatcher("inbox", on_change=self.refresh) self.watcher.start()
def refresh(self, changed): # corre en el hilo de la interfaz self.files = sorted(p.name for p in Path("inbox").glob("*"))
def view(self): return pz.column([ui.list_item(name, icon="file-text") for name in self.files], padding=16)
pz.run(Inbox)
Handlers e hilos
Sección titulada «Handlers e hilos»Pasa los handlers como on_<evento>=, o más tarde con service.on("evento", handler) (None lo quita). Un handler
con un parámetro recibe el valor del evento; uno sin parámetros simplemente se llama. Cada clase lista sus eventos en
Service.events.
Los vigilantes, los procesos, las tareas y las peticiones web trabajan en hilos en segundo plano, pero sus eventos
llegan a los handlers en el hilo de la app (con pz.post), así que un handler puede cambiar el estado de la app y
devolver comandos como cualquier callback. Sin una app en marcha, en un script o en un test, el handler se llama en
el momento, en el hilo que lanzó el evento.
service.enabled = False silencia todos sus eventos; stop() detiene lo que esté haciendo.
Los servicios
Sección titulada «Los servicios»| Clase | Lanza | Qué saber |
|---|---|---|
pz.Timer(interval=1000, repeat=True) |
tick (la cuenta) |
Milisegundos, como en Visual Basic y Qt. Devuelve timer.subscriptions() desde App.subscriptions. start(), stop(), running. |
pz.Shortcut("mod-s") |
activate (la combinación) |
Llama a shortcut.handle(combo) desde on_key. Valen "Ctrl+S", "ctrl-s, cmd-s" y mod- (Cmd en macOS, Ctrl en el resto). |
pz.FileWatcher(path, pattern="*", recursive=False, interval=500) |
created, modified, deleted (una ruta), change (la lista) |
Compara fechas y tamaños cada interval ms, así que funciona igual en todas partes, también en unidades de red. |
pz.Process(command, directory=None, env=None, shell=False) |
started, output, error_output (una línea), finished (código de salida), failed |
start(), write(text), kill(), wait(), running, exit_code. Un comando en texto se separa como lo haría una shell. |
pz.Worker(work) |
progress, done (el resultado), failed (la excepción) |
run(value) llama a work(value) en un hilo; puede usar report(progress) y mirar cancelled. |
pz.HttpRequest(url, method="GET", headers=None, body=None, timeout=30) |
response (un HttpResponse), failed |
send(); send(json={...}) envía JSON con POST. Los estados de error también son respuestas: mira response.ok. |
pz.Clipboard(watch=False, interval=500) |
change, paste (el texto) |
copy(text) y paste() devuelven comandos. Con watch, devuelve subscriptions() desde tu app. |
pz.Settings(name, folder=None, defaults=None) |
change ((clave, valor)) |
Un diccionario guardado como JSON al momento (autosave), por usuario, en la carpeta de ajustes de Pyzed. |
pz.FileDialog(mode="open", filters=..., directory=None, file_name="") |
chosen (ruta o lista), cancelled |
show() devuelve el comando que lo abre; modos open, open_many, save, folder. |
pz.Notification(title, text) |
shown, failed |
show(text=None) devuelve si se pudo mostrar. |
pz.TrayIcon(icon=None, tooltip="", menu=()) |
click, double_click (Windows), menu (el elemento), failed |
show() devuelve si pudo; hide(). Los cambios de icon, tooltip y menu se ven al momento. |
pz.SystemInfo(interval=0, disk_path=None) |
update (un diccionario) |
os, os_version, hostname, user, cpu_count, language, memory_total, memory_available, disk_free; folder("downloads"), env(name). |
pz.Launcher(target="") |
opened, failed (el destino) |
open(target) con el programa del sistema (archivos, carpetas, enlaces, mailto:), reveal(path), email(to, subject, body). |
pz.NetworkMonitor(host="1.1.1.1", port=53, interval=5000) |
change (bool), online, offline |
Prueba una conexión cada interval ms en segundo plano; online guarda la última respuesta. |
pz.PowerMonitor(interval=30000, low_level=20) |
change ((porcentaje, enchufada)), low, plugged, unplugged |
percent es None en ordenadores sin batería (has_battery). |
Un temporizador y un atajo
Sección titulada «Un temporizador y un atajo»import time
import pyzed as pz
class Clock(pz.App): def __init__(self): self.now = "" self.clock = pz.Timer(1000, on_tick=self.tick) self.quit = pz.Shortcut("mod-q", on_activate=lambda: pz.Command.exit())
def tick(self): self.now = time.strftime("%H:%M:%S")
def subscriptions(self): return self.clock.subscriptions()
def on_key(self, combo): return self.quit.handle(combo)
def view(self): return pz.text(self.now, size=48)Un comando y su salida
Sección titulada «Un comando y su salida»self.log = []self.build = pz.Process("cargo build --release", directory="engine", on_output=self.log.append, on_error_output=self.log.append, on_finished=lambda code: self.done(code == 0))self.build.start()Trabajo en segundo plano
Sección titulada «Trabajo en segundo plano»def resize_all(paths): for i, path in enumerate(paths): if worker.cancelled: return None shrink(path) worker.report((i + 1) * 100 // len(paths)) return len(paths)
worker = pz.Worker(resize_all, on_progress=self.set_progress, on_done=self.finished)worker.run(photos)Una API web
Sección titulada «Una API web»api = pz.HttpRequest("https://api.github.com/repos/albakore/pyzed", on_response=self.show_stars)api.send()
def show_stars(self, response): if response.ok: self.stars = response.json()["stargazers_count"]Ajustes y diálogos
Sección titulada «Ajustes y diálogos»prefs = pz.Settings("my-app", defaults={"theme": "One Dark"})prefs["theme"] = "One Light" # se guarda al momentoprefs.get("theme") # "One Light", también la próxima vez
dialog = pz.FileDialog("open", filters="Imágenes: png, jpg", on_chosen=self.load_image)
def open_clicked(self): return dialog.show() # un comando: devuélveloEl sistema operativo
Sección titulada «El sistema operativo»Los servicios de pyzed.system (también en el nivel superior: pz.SystemInfo, pz.Launcher…) leen el ordenador
y abren cosas con los programas que el usuario ya tiene:
info = pz.SystemInfo()f"{info.os} {info.os_version}, {info.cpu_count} núcleos" # "Windows 11, 8 núcleos"info.folder("downloads") # la carpeta Descargas del usuarioinfo.disk_free // 2**30 # GB libres
launcher = pz.Launcher(on_failed=lambda destino: print("No se pudo abrir", destino))launcher.open("https://example.com") # el navegador por defectolauncher.open("informe.pdf") # el visor de PDFlauncher.reveal("informe.pdf") # su carpeta, con el archivo seleccionado
network = pz.NetworkMonitor(on_offline=lambda: print("Sin conexión"), on_online=lambda: print("De vuelta"))network.start()Para archivos, ui.file_input es un campo de ruta con un botón que abre el diálogo del sistema, y ui.DropZone
recibe archivos arrastrados desde el escritorio. Una ventana también recibe cada archivo soltado en
on_file_drop(path) (on_file_hover y on_file_leave mientras se arrastran por encima). Mira las páginas de
Sistema de la librería.
Un icono en la bandeja
Sección titulada «Un icono en la bandeja»pz.TrayIcon pone un icono en el área de notificación de Windows, en la barra de menús de macOS y en el panel de
Linux, con un texto al pasar el ratón y un menú. El menú es una lista, o un texto con un elemento por línea: - es
un separador, [x] y [ ] crean casillas que cambian al hacer clic, y las líneas con sangría forman un submenú.
self.tray = pz.TrayIcon("icono.png", "Copias", menu="""Abrir[x] PausaVelocidad Lenta Rápida-Salir""", on_click=self.open, on_menu=self.menu)self.tray.show()
def menu(self, item): if item == "Pausa": self.paused = self.tray.checked("Pausa") elif item == "Salir": return pz.Command.exit()pz.TrayItem(text, id=None, enabled=True, checked=None, items=[]) le da a un elemento un id (lo que recibe
on_menu) o lo desactiva. Sin icon muestra un punto azul.
En Linux el icono es un StatusNotifierItem, sin GTK: KDE, Cinnamon, XFCE, MATE, LXQt y la mayoría de paneles lo
muestran, y GNOME también con la extensión AppIndicator. pz.TrayIcon.supported() dice si el escritorio muestra
iconos de bandeja; donde no, show() devuelve False y failed dice por qué.
Sin ventana
Sección titulada «Sin ventana»Nada de esto necesita una app en marcha. Los scripts y los tests pueden esperar el resultado:
import pyzed as pz
process = pz.Process(["git", "status", "--short"], on_output=print)process.start()process.wait() # espera a que termine; devuelve el código de salida
request = pz.HttpRequest("https://example.com")request.send()print(request.wait(10).status) # 200Process.wait(), Worker.wait() y HttpRequest.wait() esperan a que termine el trabajo (con un timeout
opcional) y devuelven el código de salida, el resultado o la respuesta.