[Tkinter-discuss] Unbinding Individual Events
Lion Kimbro
lionkimbro at gmail.com
Thu May 10 04:19:55 CEST 2012
Unbinding individual events from widgets has been a long standing tkinter
bug.
I've been working on a workaround for tkhelp.py, but never really liked
the solutions I came up with.
Most involved multiplexing from a single event receiver.
Here is a brief demonstration:
import tkinter
global_tk = tkinter.Tk()
def tcl(tcl_code):
"""Execute tcl code string directly & return the result."""
return global_tk.tk.eval(tcl_code)
tl = tkinter.Toplevel(name="top", width=400, height=200)
tl.title("testing")
That's the setup frame... Now:
>>> tl.bind('<Motion>', lambda evt:print(evt))
'37533768<lambda>'
Moving the mouse over the toplevel, you can see the events roll in.
Now we can look at the events in tcl:
>>> tcl('bind .top')
'<Motion>'
>>> tcl('bind .top <Motion>')
'if {"[37533768<lambda> %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X
%Y %D]" == "break"} break\n'
The important thing to recognize is that the whole string ('if
{"[375...]" == "break"} break\n') is the binding -- NOT the individual
function item '37533768<lambda>'.
Now if you add another binding --
>>> tl.bind("<Motion>", lambda evt:print("whoopie!"), add="+")
'37531848<lambda>'
You can roll the mouse over, and you'll see TWO event bindings.
Now let's look at it in detail:
>>> tcl('bind .top <Motion>')
'if {"[37533768<lambda> %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X
%Y %D]" == "break"} break\n\nif {"[37531848<l
ambda> %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y %D]" ==
"break"} break\n'
Okay, now let's say we want to remove the first method?
We can rebind, cutting it out.
First, we isolate the second entry, which we want:
>>> scripts = tcl('bind .top <Motion>')
>>> scripts.split("\n")
['if {"[37533768<lambda> %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X
%Y %D]" == "break"} break', '', 'if {"[37531
848<lambda> %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y %D]" ==
"break"} break', '']
>>> s=scripts.split("\n")[-2]
And then bind it:
>>> tcl('bind .top <Motion> {%s}' % s)
''
You'll see the "whoopie!" printing, but the first event printer will be
gone!
So my thought to systematize this is:
A. Make a function (fn-A) for making a Python list out all binding
strings on a widget-sequence pair.
B. Make a function (fn-B) that constructs the binding string for a given
function binding.
C. Patch(/replace) widget.unbind so that it retrieves all binding strings
(via fn-A), and then removes the string that matches fn-B(funcid), and then
rebind the widget via the new list
I think that should work.
My main concern is that, if _tkinter does any reference counting on
function uses, then there is a memory hole.
Thoughts?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tkinter-discuss/attachments/20120509/1988f35c/attachment-0001.html>
More information about the Tkinter-discuss
mailing list