Python Gui eventos fuera de orden

from Tkinter import * from tkMessageBox import * class Gui: def __init__(self, root): self.container = Frame(root) self.container.grid() self.inputText = Text(self.container, width=50, height=8) self.outputText = Text(self.container, width=50, height=8, bg='#E0E0E0', state=DISABLED) self.inputText.grid(row=0, column=0) self.outputText.grid(row=0, column=1) self.inputText.bind("", self.translate) def translate(self, event): input = self.inputText.get(0.0, END) output = self.outputText.get(0.0, END) self.outputText.config(state=NORMAL) self.outputText.delete(0.0, END) self.outputText.insert(INSERT, input) self.outputText.config(state=DISABLED) showinfo(message="Input: %s characters\nOutput: %s characters" % (len(input), len(input))) root = Tk() #toplevel object app = Gui(root) #call to the class where gui is defined root.mainloop() #enter event loop 

Trabajando en una interfaz gráfica de usuario en tkinter Estoy un poco confundido en cuanto a la secuencia de ejecución de los controladores de eventos. Si ejecuta el código anterior, con suerte verá …

1) La edición del widget de texto activa el controlador de eventos, pero parece que se dispara sin registrar el cambio real, 2) Incluso cuando el widget de texto se borra (es decir, sigue presionando Retroceso) aún parece tener una cadena de longitud de un carácter, 3) El widget de salida solo recibe su actualización cuando se activa el activador del evento NEXT a pesar del hecho de que los datos vinieron en el evento anterior.

¿Es así como funcionan los enlaces en tkinter o me estoy perdiendo algo aquí?

El comportamiento que me gustaría al actualizar el widget de entrada es: 1) Mostrar el cambio, 2) Ingresar al controlador de eventos, 3) Actualizar el widget de salida, 4) Mostrar el cuadro de mensaje.

Así es como funcionan los enlaces (y eso es bueno), pero su problema se resuelve fácilmente.

Los enlaces se activan en el orden especificado por las tags de enlace de los widgets (también conocidas como tags de enlace o tags de enlace). A menos que especifique lo contrario, los enlaces se realizan en el siguiente orden:

  1. si hay un enlace directamente en el widget, se activará antes que cualquier otro enlace.
  2. si hay un enlace en la clase del widget, se activa a continuación
  3. si hay un enlace en el widget de nivel superior que contiene el widget, se activa a continuación (nota: la ventana raíz se considera una ventana de nivel superior en este contexto)
  4. si hay un enlace en “todo” se disparará a continuación.

Uno de los controladores de eventos puede detener la secuencia en cualquier punto, pero eso no es el punto para esta discusión específica.

En el caso predeterminado, su enlace en ocurre antes del enlace de clase, y es el enlace de clase donde el texto se inserta realmente en el widget. Es por eso que tu atadura siempre parece estar detrás de un personaje.

Normalmente, este orden de cosas es exactamente correcto, ya que los enlaces más específicos tienen la oportunidad de anular el comportamiento predeterminado. Si no fuera así, siempre obtendrías el comportamiento predeterminado, incluso si no lo quisieras. Un lugar donde esto no siempre es lo que desea es cuando desea boost los enlaces predeterminados en lugar de reemplazarlos.

Puede intercambiar el orden de los bindtags para que el enlace de clase ocurra primero. O, agregue un bindtag adicional a su widget de texto y agréguelo en la secuencia después del enlace de clase, y conéctese a eso. Por lo general, agregar una bindtag es la mejor solución, pero no siempre.

Para cambiar los bindtags puedes hacer algo como esto:

 self.inputText.bindtags(((str(self.inputText)), "Text", "post-insert", ".", "all")) 

Para enlazar a “post-inserción”, hazlo con el método bind_class:

 self.inputText.bind_class("post-insert", "", self.translate) 

Puede parecer extraño, pero las tags de enlace son uno de los mecanismos de enlace más poderosos que existen. Le brindan un control completo y total sobre el orden de los enlaces, que es mucho más difícil con cualquier otro kit de herramientas.

Por cierto, no olvide que si obtiene todos los caracteres hasta el final del widget de texto, siempre habrá una nueva línea adicional al final. Puede llegar al end-1c o recortar una nueva línea del texto.