Proyecto final con Tkinter: diseño de una aplicación completa
En este artículo presentamos el diseño de una agenda de tareas como proyecto final para consolidar los conocimientos de Tkinter, arquitectura de software y buenas prácticas de desarrollo.
1. Visión general
La agenda permite a usuarios crear, editar, organizar y buscar tareas. Cada tarea contiene título, descripción, fecha/hora, prioridad y estado (pendiente, en progreso, completada). La aplicación está pensada para ser ligera, portátil (funciona en Windows, macOS y Linux) y extensible.
2. Requisitos funcionales
- Gestión de tareas: crear, editar, eliminar y marcar como completada.
- Filtrado y búsqueda: por fecha, prioridad y estado.
- Persistencia: guardado automático en una base de datos SQLite.
- Notificaciones: recordatorio emergente 10 min antes de la fecha límite.
- Exportar/Importar: CSV y JSON para backup.
- Temas visuales: modo claro/oscuro configurable.
3. Pantallas necesarias
3.1. Pantalla principal (Dashboard)
- Lista de tareas con columnas: título, fecha, prioridad, estado.
- Barra de herramientas con botones: Nuevo, Buscar, Filtros, Exportar, Configuración.
- Panel lateral opcional con resumen de estadísticas (tareas pendientes, próximas, completadas).
3.2. Formulario de tarea
- Campos: Título (texto), Descripción (texto multilínea), Fecha/Hora (DateEntry + TimeEntry), Prioridad (ComboBox), Estado (RadioButton).
- Botones: Guardar, Cancelar, Eliminar (solo en modo edición).
3.3. Ventana de búsqueda/filtrado
- Campo de texto libre + filtros avanzados (fecha, prioridad, estado).
- Resultados mostrados en la tabla del Dashboard.
3.4. Configuración
- Selección de tema (claro/oscuro).
- Preferencias de notificación (activar/desactivar).
- Ruta de backup.
4. Diagrama de flujo de pantallas (pseudodiagrama)
[Dashboard] ──► [Formulario de tarea] (Crear/Editar)
│ │
│ └─► (Guardar) ──► [Dashboard] (refrescar lista)
│
├─► [Búsqueda] ──► (Filtrar) ──► [Dashboard]
│
└─► [Configuración] ──► (Cambiar tema) ──► [Dashboard]
5. Estructura de clases (esqueleto)
Se adopta una arquitectura Model‑View‑Controller (MVC) ligera para separar la lógica de negocio de la UI.
class TaskModel:
"""Representa una tarea y maneja la persistencia en SQLite."""
def __init__(self, db_path: str = "tasks.db"):
self.conn = sqlite3.connect(db_path)
self._create_table()
# CRUD + búsquedas
class TaskController:
"""Orquesta la interacción entre la vista y el modelo."""
def __init__(self, model: TaskModel):
self.model = model
def add_task(self, data: dict):
self.model.insert(data)
def update_task(self, task_id: int, data: dict):
self.model.update(task_id, data)
# ... más métodos de negocio
class DashboardView(tk.Toplevel):
"""Ventana principal que muestra la tabla de tareas."""
def __init__(self, controller: TaskController):
super().__init__()
self.controller = controller
self._build_ui()
def _build_ui(self):
# Treeview, toolbar, panel lateral
pass
# callbacks de UI
class TaskFormView(tk.Toplevel):
"""Formulario modal para crear/editar una tarea."""
def __init__(self, controller: TaskController, task_id: Optional[int] = None):
super().__init__()
self.controller = controller
self.task_id = task_id
self._build_ui()
# manejo de eventos Guardar/Cancelar
class SettingsView(tk.Toplevel):
"""Ventana de configuración de la aplicación."""
def __init__(self, controller: TaskController):
super().__init__()
self.controller = controller
self._build_ui()
# cambio de tema, notificaciones
El módulo app.py instancia TaskModel, TaskController y lanza DashboardView.
6. Fragmentos clave
6.1. Creación de la tabla SQLite
def _create_table(self):
self.conn.execute('''
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
description TEXT,
due_date TEXT,
priority TEXT,
status TEXT
)
''')
self.conn.commit()
6.2. Llenado del Treeview en el Dashboard
def load_tasks(self):
for row in self.controller.model.fetch_all():
self.tree.insert('', 'end', iid=row[0], values=row[1:])
6.3. Notificación programada con threading.Timer
def schedule_reminder(task_id, due_datetime):
delta = (due_datetime - datetime.now()).total_seconds() - 600 # 10 min antes
if delta > 0:
Timer(delta, lambda: show_popup(task_id)).start()
7. Tkinter frente a otras bibliotecas GUI de Python
Ventajas de Tkinter
- Incluido en la distribución estándar de Python → cero dependencias.
- Ligero, bajo consumo de memoria.
- Fácil de empaquetar con
PyInstallerocx_Freeze. - Amplia documentación y ejemplos para principiantes.
Limitaciones y cuándo elegir otra opción
- Estética menos moderna; requiere tema personalizado o
ttkbootstrap. - Menor soporte para componentes avanzados (tablas virtuales, gráficos).
- Para aplicaciones empresariales con UI compleja, PyQt5/6 o wxPython ofrecen mayor flexibilidad.
- Si buscas integración con web‑tech (HTML/CSS) considera Electron‑Python o PyWebView.
8. Buenas prácticas y troubleshooting
8.1. Gestión de recursos
- Utiliza
with sqlite3.connect(... ) as connpara asegurar cierre correcto. - Destruye ventanas con
.destroy()y elimina referencias para evitar fugas de memoria.
8.2. Seguridad
- Escapa siempre los valores en consultas SQL o usa parámetros "?" para prevenir inyección.
- Al exportar datos, valida rutas y evita sobrescribir archivos críticos.
8.3. Rendimiento
- Para listas largas (> 1000 filas) habilita
Treeviewcondisplaycolumnsy carga bajo demanda. - Usa hilos (
threading) para operaciones de I/O (exportar CSV) sin bloquear la UI.
8.4. Depuración típica
# Error frecuente: "TclError: can't invoke "event" command" cuando se actualiza UI desde otro hilo.
# Solución: usa "after" para programar la actualización en el hilo principal.
self.root.after(0, lambda: self.tree.insert('', 'end', values=...))
9. Compatibilidad y despliegue
El proyecto está probado en:
- Python 3.9 – 3.12
- Windows 10/11, macOS 12+, distribuciones Linux basadas en Debian/Ubuntu.
Para generar un ejecutable independiente:
pyinstaller --onefile --windowed --name AgendaTareas main.py
Se recomienda firmar el binario en Windows y proporcionar un script de instalación install.sh para Linux.
19 Proyecto final con Tkinter: diseño de una aplicación completa