Deleting and changing a tkinter event binding Deleting and changing a tkinter event binding tkinter tkinter

Deleting and changing a tkinter event binding


You can simply just call bind() again with the new function for the event. Since you are not making use of the third parameter, add, in bind() this will just overwrite whatever is already there. By default this parameter is '' but it also accepts "+", which will add a callback to the callbacks already triggered by that event.

If you start using that optional argument however you will need to use the unbind() function to remove individual callbacks. When you call bind() a funcid is returned. You can pass this funcid as the second parameter to unbind().

Example:

self.btn_funcid = self.DrawArea.bind("<Button 1>", self.my_button_callback, "+")# Then some time later, to remove just the 'my_button_callback':self.DrawArea.unbind("<Button 1>", self.btn_funcid)# But if you want to remove all of the callbacks for the event:self.DrawArea.unbind("<Button 1>")


For me, unbinding a single callback wasn't working, but I found a solution.

I can see this is an old question, but for those who, like myself, find this question when facing the same problem, this is what I did to make it work.

You will need to open the source file Tkinter.py and search for the unbind method of the Misc class (if you are using eclipse it's easy to know the file's location and the line in which this function is defined by pressing the F3 key when the cursor is over an .unbind function call in your code).

When you find it, you should see something like this:

def unbind(self, sequence, funcid=None):        """Unbind for this widget for event SEQUENCE  the        function identified with FUNCID."""        self.tk.call('bind', self._w, sequence, '')        if funcid:            self.deletecommand(funcid)

You need to change it to look somethins like this:

def unbind(self, sequence, funcid=None):        """Unbind for this widget for event SEQUENCE  the        function identified with FUNCID."""    if not funcid:        self.tk.call('bind', self._w, sequence, '')        return    func_callbacks = self.tk.call('bind', self._w, sequence, None).split('\n')    new_callbacks = [l for l in func_callbacks if l[6:6 + len(funcid)] != funcid]    self.tk.call('bind', self._w, sequence, '\n'.join(new_callbacks))    self.deletecommand(funcid)

That should do the trick!


The answer provided by Bryan generally works well, but as arcra has underlined, it might not. If you experience the problem of not being able to correctly unbind a stacked callback, modifying the official source - if it is still the same! - might be a solution.

Here follow my 2 cents for those who still find themselves stuck with the problem: please, override the unbind() method, DO NOT EDIT IT DIRECTLY.

This way, in fact, you do not need to manually change the official source code on your workstation (thus breaking the package management, or reintroducing the problem at the next package update, or having the same issue on another client, ...):

import tkinter as tkclass PatchedCanvas(tk.Canvas):    def unbind(self, sequence, funcid=None):        '''        See:            http://stackoverflow.com/questions/6433369/            deleting-and-changing-a-tkinter-event-binding-in-python        '''        if not funcid:            self.tk.call('bind', self._w, sequence, '')            return        func_callbacks = self.tk.call(            'bind', self._w, sequence, None).split('\n')        new_callbacks = [            l for l in func_callbacks if l[6:6 + len(funcid)] != funcid]        self.tk.call('bind', self._w, sequence, '\n'.join(new_callbacks))        self.deletecommand(funcid)

Then, instead of instantiating your failing widget (in my example I use the Canvas) like this

myCanvas = tk.Canvas(...)

you will simply instantiate it from your patched version that will need an update if and only if the official source will be updated and fixed:

myCanvas = PatchedCanvas(...)

The unbind method is currently defined in the Misc class, from which BaseWidget inherits it and then, consequenty, Widget, TopLevel, Button, ...