Although Tkinter's derived from Tcl/Tk but it's not as complete as Tcl/Tk. Tcl/Tk bind function has some attributes which tkinter doesn't (e.g. %d that returns The detail field from the event https://www.tcl.tk/man/tcl8.4/TkCmd/bind.htm#M24).
Tcl/Tk scripts can be used by "eval" function in python but i don't know how to declare a tkinter widget in Tcl/Tk script.
so how can i use this function and its attributes on Tkinter widget?
If you are asking how to create a binding that makes use of the "data" field (ie: %d
substitution), you will have to call some tcl code to make that happen. This requires two steps: create a tcl command that calls a python function, and use tcl to bind an event to that function.
First, let's create a python program that can create an event and set the "data" field (this assumes the existence of a global variable named root
, which we'll create later). When this function is called, it will generate a custom event with the data field populated by a string.
def create_custom_event():
root.event_generate("<<Custom>>", data="Hello, world")
Next, lets create a program to call that function on a button press
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()
Next we need to create a function that is called when the event is generated. We plan to set the data
field, so this function must accept one value which is the value of the %d
substitution.
def callback(detail):
print("detail: %s" % detail)
Because you want to use the %d
substitution we'll have to create the binding via Tcl. However, tcl doesn't automatically know about our python functions so we have to register the function with tcl. Then it's just a matter of calling bind
via the tcl interface to set up the binding.
The first step, then, is to register the callback. We've already created the function, we just have to create a tcl function that calls this function. Fortunately, tkinter gives us a way to do that with the register
command. You use it like this:
cmd = root.register(callback)
This takes a python function (callback
in this case), and creates a tcl command which will call that function. register
returns the name of that tcl command which we store in a variable named cmd
(the name is irrelevant)
Next, we need to set up a binding via Tcl to call this command. If we were doing this in an actual tcl script, the command would look something like this (where "." represents the root window):
bind . <<Custom>> {callback %d}
The python equivalent is this:
root.tk.call("bind", root, "<<Custom>>", cmd + " %d")
Notice that there is a 1:1 correspondence between an argument to call
and a tcl argument. Conveniently, the default string representation of a tkinter widget is the internal tcl name, so we can directly use the widget in the call (though, pedantically, perhaps we should use str(root)
).
Putting it all together gives us this, which prints out "detail: Hello, world" when you click the button:
import tkinter as tk
def callback(detail):
print("detail: %s" % detail)
def create_custom_event():
root.event_generate("<<Custom>>", 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, "<<Custom>>", cmd + " %d")
root.mainloop()