¿Cómo usar la función de enlace Tcl / Tk en los widgets de Tkinter en Python?

Aunque Tkinter deriva de Tcl / Tk, pero no es tan completo como Tcl / Tk. La función de enlace Tcl / Tk tiene algunos atributos que tkinter no tiene (por ejemplo,% d que devuelve el campo de detalle del evento https://www.tcl.tk/man/tcl8.4/TkCmd/bind.htm#M24 ).
Los scripts Tcl / Tk pueden ser utilizados por la función “eval” en python, pero no sé cómo declarar un widget tkinter en el script Tcl / Tk.

Entonces, ¿cómo puedo usar esta función y sus atributos en el widget Tkinter?

Si está preguntando cómo crear un enlace que haga uso del campo “datos” (es decir, %d sustitución), tendrá que llamar a algún código tcl para que esto suceda. Esto requiere dos pasos: cree un comando tcl que llame a una función de python y use tcl para vincular un evento a esa función.

Primero, vamos a crear un progtwig de python que pueda crear un evento y establecer el campo “datos” (esto supone la existencia de una variable global llamada root , que crearemos más adelante). Cuando se llama a esta función, generará un evento personalizado con el campo de datos rellenado por una cadena.

 def create_custom_event(): root.event_generate("<>", data="Hello, world") 

A continuación, creamos un progtwig para llamar a esa función presionando un botón.

 import tkinter as tk root = tk.Tk() button = tk.Button(root, text="click me", command=create_custom_event) button.pack(side="top", padx=20, pady=20) root.mainloop() 

A continuación, necesitamos crear una función que se llame cuando se genera el evento. Planeamos establecer el campo de data , por lo que esta función debe aceptar un valor que es el valor de la sustitución %d .

 def callback(detail): print("detail: %s" % detail) 

Como quiere usar la sustitución %d , tendremos que crear el enlace a través de Tcl. Sin embargo, tcl no conoce automáticamente nuestras funciones de python, por lo que tenemos que registrar la función con tcl. Entonces es solo una cuestión de llamar al bind través de la interfaz tcl para configurar el enlace.

El primer paso, entonces, es registrar la callback. Ya hemos creado la función, solo tenemos que crear una función tcl que llame a esta función. Afortunadamente, tkinter nos da una manera de hacerlo con el comando de register . Lo usas así:

 cmd = root.register(callback) 

Esto toma una función de python ( callback de callback en este caso), y crea un comando tcl que llamará a esa función. register devuelve el nombre de ese comando tcl que almacenamos en una variable llamada cmd (el nombre es irrelevante)

A continuación, debemos configurar un enlace a través de Tcl para llamar a este comando. Si estuviéramos haciendo esto en un script tcl real, el comando se vería así (donde “.” Representa la ventana raíz):

 bind . <> {callback %d} 

El equivalente de python es este:

 root.tk.call("bind", root, "<>", cmd + " %d") 

Observe que hay una correspondencia 1: 1 entre un argumento para call y un argumento tcl. Convenientemente, la representación de cadena predeterminada de un widget tkinter es el nombre interno de tcl, por lo que podemos usar directamente el widget en la llamada (aunque, de forma pedante, quizás deberíamos usar str(root) ).

Ponerlo todo junto nos da esto, que imprime “detalle: Hola mundo” al hacer clic en el botón:

 import tkinter as tk def callback(detail): print("detail: %s" % detail) def create_custom_event(): root.event_generate("<>", data="Hello, world") root = tk.Tk() button = tk.Button(root, text="click me", command=create_custom_event) button.pack(side="top", padx=20, pady=20) cmd = root.register(callback) root.tk.call("bind", root, "<>", cmd + " %d") root.mainloop()