[Tkinter-discuss] Unbinding Individual Events

Michael Lange klappnase at web.de
Fri May 11 11:59:30 CEST 2012


Hi,

Thus spoketh Lion Kimbro <lionkimbro at gmail.com> 
unto us on Wed, 9 May 2012 19:19:55 -0700:

(...)
>   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?

As far as memory holes are concerned, I think cleanly unbinding each
single command, so deletecommand() will be executed, should do the trick.

Although I agree that the behavior of unbind() is not intuitive, I
think that making unbind() backwards incompatible is not a good
idea ;)

I set up a quick example, it is not perfect but seems to work ok for a
start; you see, instead of changing unbind(), I called the function that
does the work remove_binding() for now.

Best regards

Michael

##########################################
from Tkinter import *

root = Tk()
l = Listbox(root)
l.pack()

def cmd1(event):
    print '1'
def cmd2(event):
    print '2'
def cmd3(event):
    print '3'

b1 = l.bind('<Motion>', cmd1)
b2 = l.bind('<Motion>', cmd2, 1)
b3 = l.bind('<Motion>', cmd3, 1)

def bindings(widget, seq):
    return [x for x in widget.bind(seq).splitlines() if x.strip()]

def _funcid(binding):
    return binding.split()[1][3:]

def remove_binding(widget, seq, index=None, funcid=None):
    b = bindings(widget, seq)

    if not index is None:
        try:
            binding = b[index]
            widget.unbind(seq, _funcid(binding))
            b.remove(binding)
        except IndexError:
            print 'Binding #%d not defined.' % index
            return

    elif funcid:
        binding = None
        for x in b:
            if _funcid(x) == funcid:
                binding = x
                b.remove(binding)
                widget.unbind(seq, funcid)
                break
        if not binding:
            print 'Binding "%s" not defined.' % funcid
            return
    else:
        raise ValueError, 'No index or function id defined.'

    for x in b:
        widget.bind(seq, '+'+x, 1)

def test1(event):
    remove_binding(l, '<Motion>', 0)
def test2(event):
    remove_binding(l, '<Motion>', None, b1)

l.bind('<1>', test1)
l.bind('<3>', test2)

root.mainloop()
###############################################

.-.. .. ...- .   .-.. --- -. --.   .- -. -..   .--. .-. --- ... .--. . .-.

Totally illogical, there was no chance.
		-- Spock, "The Galileo Seven", stardate 2822.3


More information about the Tkinter-discuss mailing list