[Tutor] Tkinter
Michael Lange
klappnase at freenet.de
Sat Mar 6 21:47:58 EST 2004
On Sat, 6 Mar 2004 17:25:37 -0800 (PST)
Marilyn Davis <marilyn at deliberate.com> wrote:
>
> > Tk() is the application's main (or root) window; any Tkinter app
> > needs a Tk() window as parent for all the other widgets.
> >
> > That's why you have to call the mainloop() for your Tk() window to
> > keep the whole thing alive.
> >
> > The toplevel widget (called with the Toplevel() command) is a window
> > that looks just like the Tk() window, but is in fact a child of the
> > mainwindow. You don't need to call a mainloop() on Toplevel() windows.
>
> And you don't call mainloop on any "slaves"?
Right - never.
>
> Is 'slaves' the right word? I see 'master' and I see 'children'.
> Maybe 'slaves' is politically incorrect -- but technically correct? I
> don't like 'children' because it can be confused with inheritance
> hierarchies.
Most people say "parent" and "children" I think; for political correctness reasons
maybe we should use "president" and "citizens" ;-)
> > About the example with MyClass(Frame) I can just guess; maybe the
> > code looked like this:
> >
> > root = Tk()
> > o = MyClass(root)#Frame that contains some other widgets
> > o.pack()
>
> Nope, surprisingly, the examples from the Deitel book look like:
>
> # Fig. 11.5: fig11_05.py
> # Canvas paint program.
>
> from Tkinter import *
>
> class PaintBox( Frame ):
> """Demonstrate drawing on a Canvas"""
>
> def __init__( self, title='A simple paint program'):
> """Create Canvas and bind paint method to mouse dragging"""
>
> Frame.__init__( self )
> self.pack( expand = YES, fill = BOTH )
> self.master.title( title)
> self.master.geometry( "300x150" )
>
> self.message = Label( self, text = "Drag the mouse to draw" )
> self.message.pack( side = BOTTOM )
>
> # create Canvas component
> self.myCanvas = Canvas( self )
> self.myCanvas.pack( expand = YES, fill = BOTH )
>
> # bind mouse dragging event to Canvas
> self.myCanvas.bind( "<B1-Motion>", self.paint )
>
> def paint( self, event ):
> """Create an oval of radius 4 around the mouse position"""
>
> x1, y1 = ( event.x - 4 ), ( event.y - 4 )
> x2, y2 = ( event.x + 4 ), ( event.y + 4 )
> self.myCanvas.create_oval( x1, y1, x2, y2, fill = "black" )
>
> def main():
> PaintBox().mainloop()
>
> if __name__ == "__main__":
> main()
>
> --------
>
> > Now when you destroy the MyClass instance an empty window should be
> > left (the Tk() was not destroyed) which might look like a window
> > with a frame inside (an empty gray rectangle).
>
> Yes. This happened. But when I called myclass.master.destroy(), it
> all went away. So I'm thinking that if you instantiate Frame without
> a master, it automatically makes a Tk object for you to be your
> master? Or a Toplevel object for you? Probably Tk?
>
Seems like we find the magic for this in Tkinter.py, line 1717 ff.(Python2.2.1):
class BaseWidget(Misc):
"""Internal class."""
def _setup(self, master, cnf):
"""Internal function. Sets up information about children."""
if _support_default_root:
global _default_root
if not master:
if not _default_root:
_default_root = Tk()
master = _default_root
> (It's cool, the slave generates the master. Maybe that's politically
> correct.)
I guess somehow they always do so. However, viewed from this aspect I think I should
better drop the "president" / "citizen" suggestion. How about "employer" and "employees" ?
>
> I don't think I ever got it to call my __del__ method though. I wonder
> what is the relationship between destroy() and __del__(). Maybe I have
> to look at the source code some time.
>
I did so, Tkinter.py line 1760 ff. shows BaseWidget.destroy():
def destroy(self):
"""Destroy this and all descendants widgets."""
for c in self.children.values(): c.destroy()
if self.master.children.has_key(self._name):
del self.master.children[self._name]
self.tk.call('destroy', self._w)
Misc.destroy(self)
Complicated! Base.Widget.destroy() calls Misc.destroy() (Tkinter.py line 282 ff.):
def destroy(self):
"""Internal function.
Delete all Tcl commands created for
this widget in the Tcl interpreter."""
if self._tclCommands is not None:
for name in self._tclCommands:
#print '- Tkinter: deleted command', name
self.tk.deletecommand(name)
self._tclCommands = None
However, most people seem to prefer the quit() method to close Tkinter apps anyway, destroy() only to
get rid of some "employees" (mostly Toplevels I guess)
Now that I have already Tkinter.py opened, I see this is a method of the Misc class, too:
def quit(self):
"""Quit the Tcl interpreter. All widgets will be destroyed."""
self.tk.quit()
I am not that kind of expert, but I think I read something about the reasons for quit() to be the preferred method,
unfortunately I must admit I forgot about the details.
I hope this helped a little more
Michael
More information about the Tutor
mailing list