Mailing List Archive

Tk's default Toplevel - counterintuitive
Does anyone know how to tell if Tk has already instaniated a Toplevel
window? I want to be able to open several Toplevel windows in any order.

Something like:


def makeNewWindow():
if defaulttoplevel in use:
mstr=Toplevel
else:
mstr=None #Uses the default Toplevel

f = Frame(master=mstr)
...



Cheers,

Stuart

PS. Wouldn't it have made more sense if using None as a window's master
caused a new Toplevel window to be created rather than the situation now
where you end up sticking items all in the same window. The following
gives 1 window containing 3 buttons (doh!):

---
from Tkinter import *

def makeNewWindow():
f = Frame(master=None)
b=Button(master=f, text="Hello")
b.pack(side=LEFT, fill=BOTH)
Pack.config(f)

makeNewWindow()
makeNewWindow()
makeNewWindow()

---

A naive alternative is:
---
def makeNewWindow():
f = Frame( master=Toplevel() )
...as before
----

Which gives you three separate windows but a random extra empty Toplevel
window (the mystery default `None' toplevel)... DohDoh!
Tk's default Toplevel - counterintuitive [ In reply to ]
Stuart Reynolds wrote:
>
> Does anyone know how to tell if Tk has already instaniated a Toplevel
> window? I want to be able to open several Toplevel windows in any order.
>

Perhaps the easiest way is to never use the default top level window:

from Tkinter import *
DefaultTop = Tk()
DefaultTop.withdraw() # Never to be seen

def makeNewWindow():
mstr = Toplevel()
f = Frame(master=mstr)
...

You can still do
DefaultTop.mainloop()
when it time to turn control over to the main event loop

--
Dr. Gary Herron <gherron@aw.sgi.com>
206-287-5616
Alias | Wavefront
1218 3rd Ave, Suite 800, Seattle WA 98101
Tk's default Toplevel - counterintuitive [ In reply to ]
Stuart Reynolds wrote:

> Does anyone know how to tell if Tk has already instaniated a Toplevel
> window? I want to be able to open several Toplevel windows in any order.

Try this:

from Tkinter import *

def makeNewWindow():
from Tkinter import _default_root
if _default_root is not None:
master=Toplevel()
else:
master = None
f = Frame(master=master)
b = Button(master=f, text="Hello")
b.pack(side=LEFT, fill=BOTH)
Pack.config(f)

makeNewWindow()
makeNewWindow()
makeNewWindow()

NOTE - The "from Tkinter import _default_root" can be avoided by importing
Tkinter directly at the beginning (ie. "import Tkinter"), and accessing it
through
the Tkinter module. Otherwise, the _default_root reference you have won't get

updated when Tkinter changes it.
Tk's default Toplevel - counterintuitive [ In reply to ]
Gary Herron wrote:

> Stuart Reynolds wrote:
> >
> > Does anyone know how to tell if Tk has already instaniated a Toplevel
> > window? I want to be able to open several Toplevel windows in any order.
> >
>
> Perhaps the easiest way is to never use the default top level window:
>
> from Tkinter import *
> DefaultTop = Tk()
> DefaultTop.withdraw() # Never to be seen

Just be careful if you do this, to remember that if you are relying on the
behavior of closing all the visible windows to end your program, it won't.
The withdrawn() window is still running mainloop(), and needs to be
interrupted somehow. There are some ways around this using callbacks,
etc. So, depending on the behavior you prefer, this method or my method
each have their strengths.

Chad

PS. What is the way to register a callback so that you can intercept the
window manager's request to destroy a window? Then you could just bind
the sys.exit call to this on the Tk object...
Tk's default Toplevel - counterintuitive [ In reply to ]
Chad Netzer wrote:
>
> PS. What is the way to register a callback so that you can intercept the
> window manager's request to destroy a window? Then you could just bind
> the sys.exit call to this on the Tk object...

def main():
global top
top = Tk()
top.withdraw()

mb = buildMenubar()
mb.entryconfigure(2, activebackground='red')
myTop = Toplevel(menu=mb)
myTop.bind('<Destroy>', dying)


def dying(event) :
print 'Toplevel is getting destroyed'
top.quit()


The above snippet is a little ugly, but it works. Otherwise, if you kill
the visible window with the system box, the top process keeps on
chugging along. I like the Toplevel's menu setup rather than using
Menubutton's and the deprecated (atleast in the Tcl/Tk world)
tk_menuBar.




--
Bear Technology Making Montana safe for Grizzlies

http://people.montana.com/~bowman/
Tk's default Toplevel - counterintuitive [ In reply to ]
bowman <bowman@montana.com> writes:

> Chad Netzer wrote:
> >
> > PS. What is the way to register a callback so that you can intercept the
> > window manager's request to destroy a window? Then you could just bind
> > the sys.exit call to this on the Tk object...
>
> def main():
> global top
> top = Tk()
> top.withdraw()
>
> mb = buildMenubar()
> mb.entryconfigure(2, activebackground='red')
> myTop = Toplevel(menu=mb)
> myTop.bind('<Destroy>', dying)
>
>
> def dying(event) :
> print 'Toplevel is getting destroyed'
> top.quit()
>
>
> The above snippet is a little ugly, but it works. Otherwise, if you kill
> the visible window with the system box, the top process keeps on
> chugging along. I like the Toplevel's menu setup rather than using
> Menubutton's and the deprecated (atleast in the Tcl/Tk world)
> tk_menuBar.

Actually, the accepted idiom (all over the place in code I write) is

toplevel_window.protocol("WM_DELETE_WINDOW", close_callback)

The close_callback function takes no arguments. In simple cases, you
can use

root.protocol("WM_DELETE_WINDOW", root.destroy)

or

root.protocol("WM_DELETE_WINDOW", root.quit)

--Guido van Rossum (home page: http://www.python.org/~guido/)
Tk's default Toplevel - counterintuitive [ In reply to ]
Guido van Rossum <guido@cnri.reston.va.us> wrote:
> Actually, the accepted idiom (all over the place in code I write) is
>
> toplevel_window.protocol("WM_DELETE_WINDOW", close_callback)
>
> The close_callback function takes no arguments. In simple cases, you
> can use
>
> root.protocol("WM_DELETE_WINDOW", root.destroy)
>
> or
>
> root.protocol("WM_DELETE_WINDOW", root.quit)

how about making the destroy variant the
default?

</F>
Tk's default Toplevel - counterintuitive [ In reply to ]
"Fredrik Lundh" <fredrik@pythonware.com> writes:

> Guido van Rossum <guido@cnri.reston.va.us> wrote:
> > Actually, the accepted idiom (all over the place in code I write) is
> >
> > toplevel_window.protocol("WM_DELETE_WINDOW", close_callback)
> >
> > The close_callback function takes no arguments. In simple cases, you
> > can use
> >
> > root.protocol("WM_DELETE_WINDOW", root.destroy)
> >
> > or
> >
> > root.protocol("WM_DELETE_WINDOW", root.quit)
>
> how about making the destroy variant the
> default?

Good idea. I've thought of this before, and somehow never got to it.

I can't see any reason not to do it; I believe this is the default in
Tk anyway, but Tkinter's destroy() does a little more than Tk's
internal destroy. Unless I hear a clamor of complaints I'll go ahead
and do this.

--Guido van Rossum (home page: http://www.python.org/~guido/)
Tk's default Toplevel - counterintuitive [ In reply to ]
Guido van Rossum <guido@cnri.reston.va.us> wrote:
> > > root.protocol("WM_DELETE_WINDOW", root.quit)
> >
> > how about making the destroy variant the
> > default?
>
> Good idea. I've thought of this before, and somehow never got to it.

footnote: someone just pointed out that my Tkinter
introduction says:

...

as of version 1.63, Tkinter will not destroy the corresponding
widget instance hierarchy, so it is a good idea to always register
a handler yourself:

top = Toplevel(...)

# make sure widget instances are deleted
top.protocol("WM_DELETE_WINDOW", top.destroy)

Future versions of Tkinter will most likely do this by default.

FIXME: has this been changed in Python 1.5.2?

...

</F>
Tk's default Toplevel - counterintuitive [ In reply to ]
Guido van Rossum wrote:
>
> Good idea. I've thought of this before, and somehow never got to it.
> I can't see any reason not to do it;

Speaking of counterintuitive and why not?,

entrycget(index, 'menu')

returns the Tk string name of the menu, requiring a call to
nametowidget() before one can actually do something like

someMenu['bg'] = 'red'

Not a big deal, but it is rather unexpected to put a menu instance in
with entryconfigure() and get back something like '.8125431.8121234' .

--
Bear Technology Making Montana safe for Grizzlies

http://people.montana.com/~bowman/
Tk's default Toplevel - counterintuitive [ In reply to ]
On 20 Aug, Guido van Rossum wrote:
> "Fredrik Lundh" <fredrik@pythonware.com> writes:
>
> > Guido van Rossum <guido@cnri.reston.va.us> wrote:
> > > root.protocol("WM_DELETE_WINDOW", root.destroy)
> >
> > how about making the destroy variant the
> > default?
>
> I can't see any reason not to do it; I believe this is the default in
> Tk anyway, but Tkinter's destroy() does a little more than Tk's
> internal destroy. Unless I hear a clamor of complaints I'll go ahead
> and do this.

As some proof that making it the default is "a good thing", Pmw has
been doing this, behind the scenes, for some years. No one has
complained (or clamored) yet :)

--
Greg McFarlane: INMS Telstra Australia (gregm@iname.com)
Today's forecast: Sunny, with occasional cloudy periods and a chance
of precipitation in some areas.