Does not play well with Tkinter when on-quit handler invoked
Status: Beta
Brought to you by:
kbk
The following program:
import Tkinter
import sys
root = Tkinter.Tk()
console = Tkinter.Button(root, text='Done',
command=root.quit)
console.pack()
root.mainloop()
locks up the running program if "Done" is pressed. The
program stops locking when the Shell window is closed.
I observed this behaviour on Windows 2000, running
ASPN Python 2.2.
Logged In: YES
user_id=149084
Confirmed on IDLEfork/Linux. Code can be Run again, though,
don't need to close shell. Is that true for Windows?
Same program crashes Python IDLE on second button press,
something about a Tk callback error. Probably some kind of
self abuse issue?
Logged In: YES
user_id=72287
The same behavior occurs when the command is "sys.exit".
Since the 'Close Window' widget works correctly, I looked at
the Tkinter source to learn what was different. But I didn't go
very far before I encountered some example code in
Tkinter.py which uses tk.destroy as the command (where
tk=Tk()).
Once I change to "destroy", the given code exits correctly,
erasing the window.
Windows XP. IdleFork 0.92a. Python 2.2.2
Logged In: YES
user_id=72287
I have tried several work-arounds and have come up with
a quit technique which always works. Unfortunately, I
can't figure out how to change IDLEfork to accomplish the
necessary action.
The problem is that quit() (a member of the Misc class)
goes for the jugular and tries to kill the top-top-level
widget - the Tk() window opened by IDLE.
I found that walking the container chain backwards and
destroying the first 'Tk' widget works, even it Tk() is not
explicitly invoked by the application (that is,
master=None). Here's an example:
def quit(self): # where self is a Tk widget or an instance
# object with a widget attribute
parent = self
while parent.winfo_class() != 'Tk':
if parent.master == None:
break;
parent = parent.master
else:
parent.destroy()
The fact that this works indicates to me that Misc quit() is
ignoring the toplevel window for the application and
zapping IDLE's toplevel window instead.