Foros Python

Versión completa: Validad ingreso de fecha con tkinter.
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.
¿Te parece una alternativa razonable para completar el ej. que saque de tu blog?,
lo que no logro es hacer que se seleccione el total de la fecha es evidente que el
ultimo digito ingresado lo imprime después de la validación, hice varias practicas
pero no funciona.-.-

Código:
def validarFecha(fecha):
    try:
        datetime.strptime(fecha, '%d/%m/%Y')
        return 1
    except ValueError:
        return 0


def validate_entry(new_text):
    if len(new_text) > 10:
        return False

    checks = []
    for i, char in enumerate(new_text):
        if i in (2, 5):
            checks.append(char == "/")
        else:
            checks.append(char.isdecimal())
   
    if len(new_text) == 10:
        resultado = validarFecha(new_text)
        if resultado == 0:
            entrada.select_range(0, 10)
            entrada.focus()

    return all(checks)



root = tk.Tk()
root.geometry("300x200+700+300")
root.title("Mi aplicación.")

entrada = ttk.Entry(validate="key", validatecommand=(root.register(validate_entry), "%P"))
entrada.place(x=10, y=10, width=100)
entrada.focus()

root.mainloop()

Slds. Daniel ☕☕☕
Hola, Daniel.

Como bien decís, el problema es que validate_entry() se ejecuta antes de que el texto aparezca en la caja. Hay que usar otro evento que sea llamado después de que el texto es ingresado. Se podría usar <KeyRelease>, que es invocado cada vez que el usuario suelta una tecla:

Código:
def validate_entry(new_text):
    if len(new_text) > 10:
        return False

    checks = []
    for i, char in enumerate(new_text):
        if i in (2, 5):
            checks.append(char == "/")
        else:
            checks.append(char.isdecimal())

    return all(checks)


def entrada_modificada(event):
    texto = entrada.get()
    if len(texto) == 10:
        resultado = validarFecha(texto)
        if resultado == 0:
            entrada.select_range(0, tk.END)
            entrada.focus()

# [...]

entrada = ttk.Entry(validate="key", validatecommand=(root.register(validate_entry), "%P"))
entrada.place(x=10, y=10, width=100)
entrada.bind("<KeyRelease>", entrada_modificada)
entrada.focus()

Sin embargo, esta solución tiene el pequeño problema de que no se ejecutará entrada_modificada() cuando el texto no sea ingresado a través del teclado: por ejemplo, si es pegado con el mouse desde el portapapeles. Para contemplar estos otros casos habría que asociar una variable (tk.StringVar) a la caja de texto y quedar a la espera del evento que lanza cuando es modificada. Al final de este artículo hay algo sobre el tema.

Saludos
Me pone la “piel de gallina” cuando tengo que contradecir a maestros como vos
en el tema pero no puedo dejar de decirte que hice una decena de pruebas con
fechas correctas e incorrectas con copy/paste y siempre valido correctamente.-

Slds. Daniel ☕☕☕
No hay problema en que me contradigas, esa es la idea del foro de discusión Big Grin. A lo que me refería en particular es que si una fecha inválida (p. ej. 11/11/0000) es pegada desde el cortapapeles usando un menú contextual (click derecho en la caja de texto -> Pegar), la función entrada_modificada() no se ejecuta porque no hay ninguna tecla presionada, entonces el contenido no se selecciona. Pero por defecto las cajas de texto de Tk no tienen menú para copiar/pegar (aunque sí funcionan los atajos del teclado), sino que hay que implementarlo manualmente: https://recursospython.com/codigos-de-fu...tar-pegar/. Entonces, si tu caja de texto no soporta el menú de copiar/pegar, el código anterior es suficiente.

Saludos
Francisco, muy claro como siempre, ahora me quedo claro el concepto.-

Slds. Daniel ☕☕☕