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
- La tarea: si dejas de escribir, lo pierdes todo
- Analizar el problema antes de programar
- 📖 El temporizador reiniciable:
after+after_cancel - 📖 Retroalimentación visual: que el usuario "sienta" el peligro
- 📖 Diseño responsable: una app que borra tu trabajo
- 🚀 Proyecto del día: construcción por versiones
- 🌟 Proyecto extra: sesiones de concentración para estudiar
- 🏗️ Mi Portafolio Profesional — Etapa 9
- 🧩 Comprueba lo aprendido
- 🤖 Programar con apoyo de IA
- 🛠️ Observaciones sobre el material original
- 📋 Matriz de trazabilidad
- 📦 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 conbind(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":
tecla pulsada ──────► reiniciar el conteo de 5 s
pasan 5 s sin teclas ─► borrar todo3. 📖 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
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:
- Al pulsar la primera tecla,
temporizadoresNone: no hay nada que cancelar; se programa el borrado para dentro de 5 s. - En cada tecla siguiente, se cancela el borrado anterior y se programa uno nuevo.
- Si pasan 5 s sin teclas,
borrar_todose 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
- Área de texto; si pasan 5 s sin teclas, se borra todo.
- Aviso visual del tiempo restante.
- Una meta (tiempo o palabras) elegida al inicio; al cumplirla, el texto deja de estar en peligro.
- Guardar el texto en un archivo
.txtal cumplir la meta.
Restricciones técnicas
- Temporizadores con
after, nuncasleep. - Constantes para los tiempos (
LIMITE_MS), no números sueltos. - Organización en una clase (
AppEscritura) con atributos en lugar deglobal.
Planificación
- 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
AppEscrituraconself.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.mdcon 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_MSy bájala a 1000 mientras desarrollas. Así se verificó el patrón de este tutorial.
🧪 Prueba y depuración
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
- Sesiones de duración elegida (25, 45 minutos), inspiradas en el Pomodoro del Día 28.
- Área de apuntes; el mismo patrón de temporizador reiniciable detecta la inactividad, pero en vez de borrar, registra la interrupción.
- 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):
- Repositorio de la app con
README.mdque explique las reglas, las decisiones de diseño responsable (sección 5) y cómo probarla con un límite menor. - Un GIF corto mostrando el aviso visual y el borrado.
DIARIO.mddel Día 90 y ficha enproyectos.json.- 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
- ¿Qué significa "programación orientada a eventos"?
- ¿Qué devuelve
aftery para qué sirve ese valor? - ¿Por qué el borrado ocurre aunque escribas si no usas
after_cancel? - Menciona dos decisiones de diseño responsable para esta app.
Análisis de código
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.mddel Día 90, repositorio y ficha en el portafolio.- Cuaderno de errores:
aftersin cancelar, milisegundos frente a segundos,sleepen la GUI,globalolvidado, archivos guardados sinutf-8.