Saltar al contenido
Volver al inicio 100 Días de Código en Python — Día 90: Proyecto de portafolio — La app de escritura "más peligrosa"

100 Días de Código en Python — Día 90: Proyecto de portafolio — La app de escritura "más peligrosa"

Nivel: Grado décimo Área: Tecnología e Informática Modalidad: Tutorial práctico Fuente: Curso "100 Days of Code: The Complete Python Pro Bootcamp" (Angela Yu, App Brewery). Contenido del Día 90, proyecto de portafolio profesional (categoría GUI Desktop App).

Este tutorial adapta pedagógicamente el Día 90. La sección 📝 Contenido original del curso proviene del único archivo de la carpeta: dia90-tarea9.md (enunciado y pregunta de reflexión, en inglés; aquí traducido). El curso no ofrece guía ni solución, y este tutorial no entrega la aplicación terminada. Todo lo que no está en ese archivo (programación orientada a eventos, patrón de temporizador reiniciable, código de ejemplo verificado, reflexión sobre diseño ético, retos 🟢🟡🟠🔴, proyecto extra y la etapa 9 de Mi Portafolio Profesional) es creación de esta adaptación.

Nota sobre las verificaciones: el 28 de septiembre de 2026, con Python 3.14 y Tk 8.6, se ejecutó el patrón de la sección 3 con un límite reducido a 300 ms para la prueba: mientras se "escribía" una letra cada 100 ms el texto se conservó; tras la pausa, el texto se borró. La interfaz completa (barra de peligro, colores, guardado) es para completar.


Tabla de contenidos

  1. La tarea: si dejas de escribir, lo pierdes todo
  2. Analizar el problema antes de programar
  3. 📖 El temporizador reiniciable: after + after_cancel
  4. 📖 Retroalimentación visual: que el usuario "sienta" el peligro
  5. 📖 Diseño responsable: una app que borra tu trabajo
  6. 🚀 Proyecto del día: construcción por versiones
  7. 🌟 Proyecto extra: sesiones de concentración para estudiar
  8. 🏗️ Mi Portafolio Profesional — Etapa 9
  9. 🧩 Comprueba lo aprendido
  10. 🤖 Programar con apoyo de IA
  11. 🛠️ Observaciones sobre el material original
  12. 📋 Matriz de trazabilidad
  13. 📦 Evidencias de aprendizaje del Día 90

1. La tarea: si dejas de escribir, lo pierdes todo

(Fuente: dia90-tarea9.md)

📝 Contenido original del curso

Para la mayoría de los escritores, un gran problema es el bloqueo del escritor: no se te ocurre qué escribir y no escribes nada.

Una de las soluciones más interesantes es una aplicación web llamada The Most Dangerous Writing App: un editor de texto en línea donde, si dejas de escribir, pierdes todo tu progreso.

Un temporizador cuenta hacia atrás y, cuando el sitio detecta que el usuario no ha escrito nada en los últimos 5 o 10 segundos, borra todo el texto escrito hasta ese momento. (El enunciado enlaza una versión en squibler.io.)

Vas a construir una aplicación de escritorio con una funcionalidad similar. El diseño es tuyo, pero debe permitir al usuario escribir y, si se detiene más de 5 segundos, debe borrar todo lo que ha escrito.

Pregunta de la tarea — Momento de reflexión: cómo abordaste el proyecto; qué fue difícil y qué fácil; cómo mejorarías; tu mayor aprendizaje; qué harías distinto.

Prerequisitos: Tkinter y after (Días 27–28); eventos de teclado con bind (Día 86); manejo de archivos (Día 24).


2. Analizar el problema antes de programar

(Sección creada para esta adaptación.)

🔍 Antes de programar

Pregunta Respuesta que debes construir tú
¿Qué evento indica que el usuario "está escribiendo"? Cada pulsación de tecla
¿Qué pasa en cada pulsación? El conteo de 5 s vuelve a empezar
¿Qué pasa si pasan 5 s sin teclas? Se borra todo
¿Cuándo empieza el juego? ¿Al abrir la app o con la primera tecla?
¿Cómo termina bien? ¿Al llegar a N palabras? ¿Tras X minutos? Entonces el texto se puede guardar
¿Qué cuenta como "escribir"? ¿Flechas y Mayús también reinician? ¿Retroceso? (decide y justifica)

Programación orientada a eventos

Hasta el Día 14, tus programas seguían un camino de arriba a abajo. En una GUI, el programa espera (mainloop) y reacciona a eventos: una tecla, un clic, un temporizador que se cumple. Este proyecto tiene dos fuentes de eventos que "compiten":

Texto
  tecla pulsada ──────► reiniciar el conteo de 5 s
  pasan 5 s sin teclas ─► borrar todo

3. 📖 El temporizador reiniciable: after + after_cancel

(Sección creada para esta adaptación. Patrón verificado.)

🎯 Objetivo de aprendizaje

Programar una acción que ocurre solo si no sucede otro evento durante cierto tiempo.

📖 Explicación conceptual

ventana.after(ms, funcion) programa funcion y devuelve un identificador. Con ese identificador, ventana.after_cancel(identificador) la cancela antes de que ocurra. Idea: en cada tecla, cancelar el borrado pendiente y programar uno nuevo.

Es como el temporizador de una luz de pasillo con sensor: cada vez que alguien pasa, vuelve a contar desde cero; solo se apaga si nadie pasa en un rato. (En programación, a este patrón se le llama a veces debounce.)

🔎 Ejemplo explicado

Python
import tkinter as tk

LIMITE_MS = 5000

ventana = tk.Tk()
ventana.title("Escribe o pierde")
texto = tk.Text(ventana, font=("Georgia", 14), wrap="word")
texto.pack(fill="both", expand=True)

temporizador = None

def borrar_todo():
    texto.delete("1.0", "end")

def reiniciar_temporizador(evento=None):
    global temporizador
    if temporizador is not None:
        ventana.after_cancel(temporizador)
    temporizador = ventana.after(LIMITE_MS, borrar_todo)

texto.bind("<KeyPress>", reiniciar_temporizador)
ventana.mainloop()

Cómo funciona:

  1. Al pulsar la primera tecla, temporizador es None: no hay nada que cancelar; se programa el borrado para dentro de 5 s.
  2. En cada tecla siguiente, se cancela el borrado anterior y se programa uno nuevo.
  3. Si pasan 5 s sin teclas, borrar_todo se ejecuta: texto.delete("1.0", "end") borra desde la línea 1, carácter 0, hasta el final.

Verificado: con el límite en 300 ms y una letra cada 100 ms, el texto se conservó; 300 ms después de la última letra, se borró.

Alternativa sin cancelar: guardar la hora de la última tecla (time.monotonic()) y tener un único after que se repite cada 100 ms y comprueba ahora - ultima_tecla > 5. Ventaja: el mismo ciclo sirve para actualizar la barra de peligro (sección 4). Compara ambos enfoques y elige.

⚠️ Errores frecuentes

Error Qué ocurre Por qué Solución
No cancelar el after anterior El texto se borra aunque sigas escribiendo El primer after programado se cumple a los 5 s de la primera tecla after_cancel antes de programar otro
time.sleep(5) La ventana se congela sleep bloquea mainloop after
Olvidar global temporizador UnboundLocalError o nunca se cancela La asignación crea una variable local global o, mejor, una clase con self.temporizador
after(5, ...) Borra casi al instante after usa milisegundos after(5000, ...)
<Key> vs. <KeyPress> vs. <KeyRelease> Diferencias sutiles Mantener una tecla pulsada genera varios KeyPress Decide cuál usar y pruébalo

4. 📖 Retroalimentación visual: que el usuario "sienta" el peligro

(Sección creada para esta adaptación.)

Una buena interfaz avisa antes de castigar. Ideas (elige y combina):

Idea Cómo en Tkinter
Barra que se vacía ttk.Progressbar o un Canvas con un rectángulo cuyo ancho cambias con coords
Fondo que se vuelve rojo Calcular un color según el tiempo restante y texto.config(bg=...)
Texto que se desvanece Cambiar el color del texto de negro a gris claro (fg)
Cuenta regresiva numérica Label actualizado cada 100 ms
Contador de palabras len(texto.get("1.0", "end-1c").split())

Ejemplo de cálculo de color (tú lo programas): si quedan 5 s el fondo es blanco (#ffffff); a 0 s, rojo claro (#ffcccc). Interpola el componente verde y azul entre 255 y 204 según la fracción de tiempo restante y forma el color con f"#ff{g:02x}{b:02x}". (:02x escribe un número en hexadecimal con 2 dígitos, como los colores del Día 43.)


5. 📖 Diseño responsable: una app que borra tu trabajo

(Sección creada para esta adaptación.)

Esta app destruye el trabajo del usuario a propósito. Eso puede motivar… o angustiar. Un desarrollador responsable piensa en quién la usa:

  • Consentimiento claro: una pantalla inicial que explique las reglas antes de empezar.
  • Meta alcanzable: al llegar a la meta (por ejemplo, 5 minutos o 200 palabras), el texto queda a salvo y se puede guardar.
  • Modo práctica: un modo en que, en lugar de borrar, solo se desvanece el texto (el usuario elige).
  • Nada de trampas ocultas: si hay un botón de "guardar", que funcione de verdad.

💬 Para discutir en clase: ¿es ético diseñar software que usa la presión o el miedo para cambiar el comportamiento? Piensa en apps que usan notificaciones, rachas o contadores para retenerte. ¿Dónde está el límite entre ayudar y manipular?


6. 🚀 Proyecto del día: construcción por versiones

(Desarrolla la tarea dia90-tarea9.md. Las versiones son una propuesta de esta adaptación.)

Problema

Construir una aplicación de escritorio que borre todo el texto si el usuario deja de escribir más de 5 segundos.

Contexto

En la clase de lenguaje se practica escritura libre para vencer el miedo a la hoja en blanco: 10 minutos escribiendo sin detenerse ni corregir.

Objetivo

Una app Tkinter con la regla de los 5 s, aviso visual, meta de sesión y opción de guardar al cumplirla.

Requisitos funcionales

  1. Área de texto; si pasan 5 s sin teclas, se borra todo.
  2. Aviso visual del tiempo restante.
  3. Una meta (tiempo o palabras) elegida al inicio; al cumplirla, el texto deja de estar en peligro.
  4. Guardar el texto en un archivo .txt al cumplir la meta.

Restricciones técnicas

  • Temporizadores con after, nunca sleep.
  • Constantes para los tiempos (LIMITE_MS), no números sueltos.
  • Organización en una clase (AppEscritura) con atributos en lugar de global.

Planificación

  1. Comprender (prueba la versión web del enunciado). 2. Entradas: teclas. 3. Procesos: reiniciar/borrar/avisar/cumplir meta. 4. Salidas: texto, aviso, archivo. 5. Dividir en funciones o métodos. 6. Bocetar la ventana. 7. Implementar. 8. Probar. 9. Corregir. 10. Mejorar.

Construcción paso a paso

  • Versión 1 — Núcleo: el ejemplo de la sección 3 funcionando.
  • Versión 2 — Clase: reorganiza en AppEscritura con self.temporizador.
  • Versión 3 — Aviso visual: barra o color según el tiempo restante.
  • Versión 4 — Meta: pantalla inicial con reglas y meta; contador de palabras y tiempo.
  • Versión 5 — Guardar: al cumplir la meta, habilitar "Guardar" (filedialog.asksaveasfilename).
  • Versión final: README.md con capturas y diario.

Pruebas

# Caso Resultado esperado
1 Escribir sin parar 20 s Nada se borra
2 Escribir y detenerse 6 s Todo se borra
3 Detenerse 4 s y seguir Nada se borra; el aviso vuelve a "seguro"
4 Abrir la app y no escribir Decide: ¿se borra algo? ¿empieza el conteo? (coherente con tu diseño)
5 Cumplir la meta y esperar 10 s El texto no se borra
6 Guardar El .txt contiene el texto con tildes correctas (encoding="utf-8")

💡 Probar sin esperar 5 s cada vez: usa una constante LIMITE_MS y bájala a 1000 mientras desarrollas. Así se verificó el patrón de este tutorial.

🧪 Prueba y depuración

Python
def al_escribir(evento):
    ventana.after(5, borrar_todo)

texto.bind("<KeyPress>", al_escribir)

Encuentra dos problemas: nunca cancela los borrados anteriores (se borra 5 s después de la primera tecla, siempre), y 5 son milisegundos, no segundos.

⭐ Extensión del proyecto

  • 🟢 Reto 1 — Aplicación: el usuario elige el límite (5, 10 o 15 s) en la pantalla inicial.
  • 🟡 Reto 2 — Ampliación: "modo difícil": el texto se desvanece progresivamente en lugar de borrarse de golpe, y se recupera si vuelves a escribir a tiempo.
  • 🟠 Reto 3 — Desafío: consignas aleatorias (prompts) desde un archivo JSON al empezar ("Describe tu lugar favorito del colegio…").
  • 🔴 Reto 4 — Pensamiento computacional: estadísticas de sesiones (palabras por minuto, pausas más largas, sesiones completadas). Diseña qué datos guardar, cómo mostrar el progreso a lo largo de semanas y cómo hacerlo sin guardar el contenido de los textos (privacidad).

7. 🌟 Proyecto extra: sesiones de concentración para estudiar

(Proyecto creado para esta adaptación; no existe en el curso original.)

Situación

Un estudiante se distrae con el celular mientras estudia. Quiere una app de escritorio que registre sesiones de concentración: si durante la sesión no hay actividad en la app (por ejemplo, tomando apuntes) en 2 minutos, la sesión se marca como "interrumpida".

Requisitos

  1. Sesiones de duración elegida (25, 45 minutos), inspiradas en el Pomodoro del Día 28.
  2. Área de apuntes; el mismo patrón de temporizador reiniciable detecta la inactividad, pero en vez de borrar, registra la interrupción.
  3. Historial en JSON y resumen semanal.

Decisiones que debes tomar (y justificar)

  • ¿Qué cuenta como "actividad"? ¿Solo teclas? ¿Mover el ratón sobre la ventana?
  • ¿Cómo evitar que la app se sienta como un "vigilante" y no como una ayuda?

Casos de prueba

  • Una sesión sin pausas largas queda como "completa".
  • El historial sobrevive al cerrar la app.

8. 🏗️ Mi Portafolio Profesional — Etapa 9

(Proyecto integrador creado para esta adaptación; etapas anteriores en los Días 82 a 89.)

Etapa 9 (hoy):

  1. Repositorio de la app con README.md que explique las reglas, las decisiones de diseño responsable (sección 5) y cómo probarla con un límite menor.
  2. Un GIF corto mostrando el aviso visual y el borrado.
  3. DIARIO.md del Día 90 y ficha en proyectos.json.
  4. Revisa tus proyectos de GUI (Días 85, 86 y 90): ¿repites código (por ejemplo, el temporizador)? Anota en tu diario qué podrías extraer a un módulo reutilizable.

9. 🧩 Comprueba lo aprendido

Conceptuales

  1. ¿Qué significa "programación orientada a eventos"?
  2. ¿Qué devuelve after y para qué sirve ese valor?
  3. ¿Por qué el borrado ocurre aunque escribas si no usas after_cancel?
  4. Menciona dos decisiones de diseño responsable para esta app.

Análisis de código

Python
temporizador = ventana.after(5000, borrar_todo)
ventana.after_cancel(temporizador)

¿Se ejecuta borrar_todo? ¿Por qué?

Predicción

Con el ejemplo de la sección 3, escribes "hola" en 2 segundos y luego esperas. ¿Cuántos segundos después de abrir la app se borra el texto? (Suponiendo que empezaste a escribir al segundo 0.)

Depuración

"Mi app funciona, pero a veces el texto se borra mientras mantengo presionada la tecla Retroceso." ¿Es un error o una característica? ¿Cómo lo investigarías?

Modificación

Cambia el ejemplo para que, en vez de borrar todo, borre solo la última palabra cada 5 s de inactividad.

Creación

Escribe color_peligro(fraccion) que reciba un número entre 0 (sin peligro) y 1 (a punto de borrar) y devuelva un color hexadecimal entre blanco y rojo claro.


10. 🤖 Programar con apoyo de IA

Ciclo de trabajo: formula el problema → inténtalo tú primero → consulta a la IA sobre un punto concreto → lee y entiende → prueba → compara con la documentación oficial → modifica → explica con tus palabras.

Actividad 1 — Conceptos. Pregunta a una IA qué es el patrón debounce. Explica con tus palabras cómo se relaciona con tu app.

Actividad 2 — Pruebas rápidas. Pide a una IA ideas para probar una app con temporizadores sin esperar el tiempo real. Compara con el consejo de la sección 6 y aplica al menos una.

Actividad 3 — Ética. Pregunta a una IA por ejemplos de "patrones oscuros" (dark patterns) en aplicaciones. Busca una fuente confiable que los defina y revisa que tu app no use ninguno.

Declara el uso: sección "Uso de IA" en el README.md.


11. 🛠️ Observaciones sobre el material original

Archivo Observación Tratamiento
dia90-tarea9.md Menciona "5/10 segundos" y luego exige "más de 5 segundos" Se usa 5 s como requisito y el límite configurable como reto 1
dia90-tarea9.md No dice cuándo termina una sesión ni si se puede guardar Sección 5 y requisitos 3–4: meta y guardado
dia90-tarea9.md Enlaza la versión web de squibler.io Se conserva como referencia; su diseño puede haber cambiado
dia90-tarea9.md No menciona el efecto en el usuario Sección 5: diseño responsable

12. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
Bloqueo del escritor y The Most Dangerous Writing App dia90-tarea9.md Secciones 1 y 2 — Reto 3 (consignas) Sección 6 (contexto)
Temporizador: si no escribe en 5/10 s, se borra todo dia90-tarea9.md Sección 3 App de escritura Retos 1 y 2 Secciones 6 y 8
App de escritorio; diseño libre dia90-tarea9.md Sección 4 App de escritura Reto 4 Sección 6
Momento de reflexión dia90-tarea9.md Sección 6 (versión final) Pregunta de reflexión — Sección 8
(No existe en el curso original) — Eventos, debounce, diseño responsable — Sesiones de concentración Sección 7

13. 📦 Evidencias de aprendizaje del Día 90

  • La app funcionando (GIF con el aviso y el borrado; captura del guardado al cumplir la meta).
  • La tabla de pruebas completada.
  • Reflexión escrita sobre diseño responsable (sección 5).
  • DIARIO.md del Día 90, repositorio y ficha en el portafolio.
  • Cuaderno de errores: after sin cancelar, milisegundos frente a segundos, sleep en la GUI, global olvidado, archivos guardados sin utf-8.