I have problems when destroying a window that has a bind to an external widget.
For example, I have one root window, and many different subwindows (in the code is the same one to make it simple).
When I open a subwindow from the root.
It creates a window and binds to a signal from the root window.
All the subwindows will bind to this same signal but to a different callbacks (one for each subwindow).
Then when I destroy this subwindow (click X in the top corner) the bind still alive, this means the subwindow still alive.
The question is:
How do I destroy the subwindow with its bind, leaving the other callbacks alive?
In the subwindow _destroy method, I have tried
root.unbind("<<EverybodyDoSomething>>", self.bind1)
but I get an error
TclError: can’t delete Tcl command
And if I use
root.unbind("<<EverybodyDoSomething>>")
All the callbacks assosiated with the signal get unbinded.
import Tkinter as Tk
root = Tk.Tk()
i_window = 0
def generate_dosomething_signal():
root.event_generate('<<EverybodyDoSomething>>', when = 'tail')
def subwindow():
SubWindow()
class SubWindow(Tk.Tk):
def __init__(self):
global i_window
Tk.Tk.__init__(self)
self.i = str(i_window)
i_window += 1
l = Tk.Label(master=self, text='This is s Sub Window %s!!!!'%self.i)
l.pack()
self.bind1 = root.bind('<<EverybodyDoSomething>>',
self.callback_from_sub_window, '+')
self.bind('<Destroy>', self._destroy)
def _destroy(self, *args):
# root.unbind('<<EverybodyDoSomething>>', self.bind1)
# root.unbind('<<EverybodyDoSomething>>')
pass
def callback_from_sub_window(self, *args):
print 'callback from Sub Window ' + self.i
bStartWindow = Tk.Button(master=root, text='Start Sub Window', command=subwindow)
bStartWindow.pack()
bDoSomethingEverywhere = Tk.Button(master=root, text='Do something everywhere',
command = generate_dosomething_signal)
bDoSomethingEverywhere.pack()
root.mainloop()
What you say isn’t the normal behavior of Tkinter. Normally when you destroy a widget, all of its children widgets get destroyed too. When they get destroyed, their bindings go with them.
Most likely, the root of your problem lies in the fact you are creating more than one instance of the root widget. You simply cannot do this. A Tkinter application must have exactly one instance of
Tk, and exactly one instance of a runningmainloop.If you want more than one top level window, create instances of Toplevel for your second and subsequent windows.
Also, you should not be using
bind(...,"+")to accomplish this task. As you’ve discovered, there is no way to remove such a binding. You can completely remove all bindings to<<EverybodyDoSomething>>, but you can’t remove only one part that was added withbind(..."+").What you need to do instead is have a single binding that calls a single function. This function can then iterate over a list of toplevel windows, sending the event to each window. You can simply skip any windows that no longer exist. You can either use introspection to get a list of toplevel windows, or you can manually maintain this list by appending a window reference each time your code creates one.