Pyzed vs Dear PyGui
Dear PyGui envuelve Dear ImGui, el toolkit en modo inmediato que usan los motores de videojuegos para sus herramientas de depuración. Se dibuja por GPU y es muy rápido, y brilla en gráficas en tiempo real, editores de nodos y herramientas internas. Su aspecto es el de «herramienta» de ImGui, y redibuja continuamente, algo que encaja mejor en un panel que cambia en cada fotograma que en un formulario que cambia cuando haces clic.
En resumen
Sección titulada «En resumen»| Pyzed | Dear PyGui | |
|---|---|---|
| Modelo | Estado + view() (arquitectura Elm) |
Elementos creados una vez con etiquetas, cambiados con set_value / configure_item |
| Redibujado | Cuando algo cambia | En cada fotograma, por defecto |
| Aspecto | Componentes modernos listos, temas, modo oscuro | Estilo de herramienta ImGui, configurable con temas |
| Texto | Shaping completo, cualquier escritura, emoji, texto enriquecido y markdown | Fuentes y rangos de glifos que cargas tú |
| Gráficas | Sparklines, barras y donuts, un canvas | Excelentes gráficas integradas (ImPlot) |
| Escritorio | Menús, atajos, varias ventanas, docks, editor de código | Docking y viewports de ImGui |
| Diseñador, recarga | Pyzed Design, pyzed dev |
– |
| Accesibilidad | Teclado; sin lectores de pantalla todavía | Sin lectores de pantalla |
El mismo contador
Sección titulada «El mismo contador»"""Reference app: a counter with -, + and Reset."""
import pyzed as pzfrom pyzed import ui
class Counter(pz.App): title = "Counter" size = (320, 200)
def __init__(self): self.count = 0
def add(self, step): self.count += step
def view(self): return pz.center(pz.column([ ui.heading(str(self.count)), pz.row([ ui.button(icon="minus", on_press=lambda: self.add(-1)), ui.button(icon="plus", on_press=lambda: self.add(1), variant="solid"), ui.button("Reset", lambda: setattr(self, "count", 0), variant="ghost"), ], spacing=8), ], spacing=16, align="center"))
pz.run(Counter)"""Reference app: a counter with -, + and Reset."""
import dearpygui.dearpygui as dpg
dpg.create_context()count = 0
def change(step): global count count = 0 if step is None else count + step dpg.set_value("count", str(count))
with dpg.window(tag="main"): dpg.add_text("0", tag="count") with dpg.group(horizontal=True): dpg.add_button(label="-", callback=lambda: change(-1)) dpg.add_button(label="+", callback=lambda: change(1)) dpg.add_button(label="Reset", callback=lambda: change(None))dpg.create_viewport(title="Counter", width=320, height=200)dpg.setup_dearpygui()dpg.show_viewport()dpg.set_primary_window("main", True)dpg.start_dearpygui()dpg.destroy_context()La misma lista de tareas
Sección titulada «La misma lista de tareas»"""Reference app: add tasks (button or Enter), tick them off, delete them, see how many are left."""
import pyzed as pzfrom pyzed import ui
class Todo(pz.App): title = "To-do" size = (420, 480)
def __init__(self): self.tasks = [] # [title, done] self.draft = ""
def add(self): if self.draft.strip(): self.tasks.append([self.draft.strip(), False]) self.draft = ""
def toggle(self, task, done): task[1] = done
def row(self, task): return pz.row([ ui.checkbox(task[1], lambda done: self.toggle(task, done)), ui.label(task[0], color="text_muted" if task[1] else "text", width="fill"), ui.icon_button("trash-2", lambda: self.tasks.remove(task)), ], spacing=8, align="center")
def view(self): left = sum(not done for _, done in self.tasks) return pz.column([ ui.heading(f"{left} left", level=3), pz.row([ ui.input(self.draft, lambda text: setattr(self, "draft", text), on_submit=self.add), ui.button("Add", self.add, variant="solid"), ], spacing=8), pz.scrollable(pz.column([self.row(t) for t in self.tasks], spacing=4), height="fill"), ], spacing=12, padding=16)
pz.run(Todo)"""Reference app: add tasks (button or Enter), tick them off, delete them, see how many are left."""
import dearpygui.dearpygui as dpg
dpg.create_context()tasks = [] # [title, done]
def refresh(): dpg.delete_item("list", children_only=True) for task in tasks: with dpg.group(horizontal=True, parent="list"): dpg.add_checkbox(label=task[0], default_value=task[1], callback=lambda s, value, t=task: (t.__setitem__(1, value), refresh())) dpg.add_button(label="Delete", callback=lambda s, a, t=task: (tasks.remove(t), refresh())) dpg.set_value("left", f"{sum(not done for _, done in tasks)} left")
def add(): text = dpg.get_value("entry").strip() if text: tasks.append([text, False]) dpg.set_value("entry", "") refresh()
with dpg.window(tag="main"): dpg.add_text("0 left", tag="left") with dpg.group(horizontal=True): dpg.add_input_text(tag="entry", width=300, on_enter=True, callback=add) dpg.add_button(label="Add", callback=add) dpg.add_child_window(tag="list")dpg.create_viewport(title="To-do", width=420, height=480)dpg.setup_dearpygui()dpg.show_viewport()dpg.set_primary_window("main", True)dpg.start_dearpygui()dpg.destroy_context()Medianas de los benchmarks (Linux, sin GPU: ambos renderizan con los drivers por software de Mesa).
| Medición (menor es mejor en todas las filas) | Pyzed 1.2.0 | Dear PyGui 2.3.1 |
|---|---|---|
| Importar la biblioteca | 35 ms | 17 ms |
| Primer fotograma, 10 filas | 165 ms | 133 ms |
| Primer fotograma, 1.000 filas | 243 ms | 152 ms |
| Memoria (RSS), 10 filas | 151 MB | 123 MB |
| Memoria (RSS), 1.000 filas | 161 MB | 125 MB |
| Actualizar 1.000 filas | 18 ms | 6.6 ms |
| Líneas: contador | 19 líneas | 19 líneas |
| Líneas: lista de tareas | 31 líneas | 29 líneas |
De los conceptos de Dear PyGui a Pyzed
Sección titulada «De los conceptos de Dear PyGui a Pyzed»| Dear PyGui | Pyzed |
|---|---|
create_context, create_viewport, start_dearpygui |
pz.run(MiApp) |
with dpg.window(...) |
la raíz que devuelve view() |
dpg.add_text(tag="x") + dpg.set_value("x", ...) |
ui.label(self.x): cambia self.x |
callback=fn |
on_press=fn |
dpg.group(horizontal=True) |
pz.row |
dpg.child_window |
pz.scrollable, ui.card, ui.panel |
dpg.theme() + bind_item_theme |
temas y estilos |
dpg.add_plot |
ui.bar_chart, ui.sparkline, o pz.canvas para dibujo propio |
Cuándo elegir cada uno
Sección titulada «Cuándo elegir cada uno»- Elige Dear PyGui para gráficas en tiempo real, editores de nodos, paneles de instrumentos y herramientas de depuración donde el aspecto de ImGui está bien.
- Elige Pyzed para apps de usuario final: formularios, listas, editores y paneles que deban verse pulidos, con texto de calidad, un diseñador, recarga en caliente y empaquetado.