Foros Python

Versión completa: Capturar un evento antes que ocurra, tkinter.-
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.
Hola gente, ¿cómo están? Hola Francisco.
Créanme que como siempre antes de pedir ayuda busco práctico
y como en este caso cuando tengo que tirar la toalla recurro a Uds.
La consulta concreta es ¿hay alguna manera de capturar el evento
antes que se efectivice?, o ¿tiene esto otra solución?.-
En apariencia funciona, lo que ocurre es que cuando se ejecuta
la excepción el IDE se queda como en un bucle infinito y no se deja
cerrar.

Código:
#-------------------------------------------------------------------------------
# Name:        módulo1
# Purpose:     Copiar/pegar
#
# Author:      Daniel
#
# Created:     11/08/2022
# Copyright:   (c) Daniel 2022
# Licence:     <your licence>
#-------------------------------------------------------------------------------
import tkinter as tk
from tkinter import ttk
from functools import partial
import funciones

def rehacer(text, temp, event):
    try:
        text.edit_undo()
    except:
        text.insert(tk.INSERT, temp)

    return


def main():

    root = tk.Tk()

    text = tk.Text(root,width = 55,height = 10, undo=True)
    text.pack()

    temp = """ La inteligencia no se mide por el número
de palabras que sabes pronunciar,
sino por aquellas que no dices para no lastimar!!!
"""

    text.insert(tk.INSERT, temp)

    root.bind('<Control-z>', partial(rehacer, text, temp))
   
    root.mainloop()


if __name__ == '__main__':
    main()



Bueno, es todo, desde ya gracias, muchas gracias por el tiempo.

Slds. Daniel ☕☕☕
Hola, Daniel, ¿cómo estás?

No veo necesario que asocies el evento Ctrl + Z manualmente, eso ya lo hace por defecto el tk.Text (lo mismo que Ctrl + Y para rehacer). Cada vez que el usuario presiona Ctrl + Z, se genera un evento llamado <<Undo>>. Podés asociarle una función y retornar la cadena "break" cuando quieras abortar la propagación del evento.

Código:
import tkinter as tk


def undo(event):
    print("Deshacer cancelado.")
    # Cancelar el evento (tal vez con un condicional).
    return "break"


def main():
    root = tk.Tk()
    text = tk.Text(root, width=55, height=10, undo=True)
    text.pack()
    temp = """ La inteligencia no se mide por el número
de palabras que sabes pronunciar,
sino por aquellas que no dices para no lastimar!!!
"""
    text.insert(tk.INSERT, temp)
    text.bind("<<Undo>>", undo)
    root.mainloop()


if __name__ == '__main__':
    main()

Saludos
Hola Francisco, que tengas un buen día, hola a todos.-
Bien, muy bueno, lo tuyo y en cuanto a la función "rehacer"
sabía que no tenía sentido, pero la puse con el afán de darme
a entender, desconocía tu función.-
Bueno y ahora, ¿cómo le doy sentido a ese condicional?, se
me antoja que si tendría acceso a la pila(que me imagino es
una lista) tendría forma de evitar que el TEXT me quede vacío,
¿eso no es factible no?.-

te dejo un ej. de lo que me pasa:

agrego 123
          456
          789

Si pulso <Control-z> 1 vez queda:
            123
            456

Si pulso <Control-z> otra vez queda:
            123
                     
Pulso <Control-z> otra vez deja el TEXT vacío, esto es lo que
deseo evitar... 


Slds. Daniel ☕☕☕
Hola, Daniel.

No andás con cosas fáciles vos... Big Grin

A la pila de operaciones que utiliza internamente el mecanismo de hacer/rehacer no es posible acceder. En realidad es una estructura implementada en C que almacena comandos de Tcl (insert, delete, etc.). Incluso si tuviéramos acceso, sería muy difícil determinar si el comando que está por ejecutarse va a dejar nuestra caja de texto vacía o no. Por ende lo único que se me ocurre es chequear si la caja de texto ha quedado vacía inmediatamente despúes de cada evento de deshacer, y en tal caso ejecutar edit_redo() para rehacer los cambios. No sé si es la solución más óptima, pero ahora creo que no se puede hacer otra cosa:

Código:
import tkinter as tk


def undo_before(event):
    event.widget.after(1, undo_after, event)


def undo_after(event):
    # Si el texto queda vacío, rehacer la última operación.
    if not event.widget.get("1.0", tk.END).strip():
        event.widget.edit_redo()


def main():
    root = tk.Tk()
    text = tk.Text(root, width=55, height=10, undo=True)
    text.pack()
    text.bind("<<Undo>>", undo_before)
    root.mainloop()


if __name__ == "__main__":
    main()

¡Saludos!
Hola Francisco, ¿habré intentado pasarme de la raya? jajajajajaja
Gracias por tu tiempo y el código.-

Slds. Daniel ☕☕☕
Hola, ¿ cómo están?, buen día para todos.
Aquí les traigo algo interesante que soluciona todo con una línea.-

Código:
text.insert(tk.INSERT, temp)
text.edit_reset()

Les doy mi parecer, no lo den por sentado porque no lo encontré
escrito en ningún lado, tan solo se me ocurrió.-

Si hay algo escrito en el text al iniciar la pila lo copia y si luego
escribimos por ej.:

123
456

Al Deshacer primero borra 456 (último en entrar, primero en salir)
luego borra 123
y al final borrara lo primero que copio(el texto del widget text)
Si al iniciar ponemos la línea "text.edit_reset()" el text nunca quedará
vacío.-

Slds. Daniel ☕☕☕
¡Excelente, Daniel! Gracias por compartirlo.