tkMessageBox returns 'can't invoke "frame" command:' error

Carel Fellinger cfelling at iae.nl
Thu Jun 24 21:41:25 CEST 1999


Hai Raymond,

though I'm new to python and Tkinter myself, I think I know what the
problem is. I tried it out at my site and it seems to work. And if
there is any truth in what I am going to tell (please you higher
gods, correct me if i'm wrong) I have finally fathomed the difference
between quit and destroy whilst figuring out your bug:).

The point is that you repeatedly try to initialise Tkinter without
properly finishing up prior uses. You correctly call widget.quit(), but
this doesn't destroy the widget, it merely exits the widget.mainloop().
This can easily be seen: after finishing the first import of your code
in the interactive interpretor by pressing the 'quit' button, you will
notice that the window doesn't disappear. Though this window is kind of
dead in not reacting to clicking it is still there. And so is your
invocation of Tkinter. If at this point you reload your script you might
notice that the default window label now reads "Tk #2" to remind you of
the fact that you now have a second invocation of Tkinter running at the
same time.

The way out is simple, you have to explicitly destroy your widgets.
a simple "rootWindow.destroy()" after the call to mainloop will do.


As for your error message complaining about the frame command not working
because the application has been destroyed, that's a little trickier.
Just where should I start...

First, Tkinter keeps track of the current Tk invocation using the var
Tkinter._default_root, initially this equals None, and upon invocing
Tk() it gets initialised. Unfortunately Tkinter doesn't reset this
var to None upon termination of Tk through an appropriate destroy()!
(maybe this should be considered a bug? who should know about it?)

Second, many (all?) widget commands have None as default for the master
keyword-arg. And if you don't specify an explicit master for the widget
the before mentioned Tkinter._default_root will be used. But elas,
the second time around (reloading your script) this still refers to the
now obsolete Tk instantiation. Hence the Tcl error: that Tk doesn't
exist anymore.

There are two ways to remedy this:
1) add something like "master=rootWindow" to constructor calls of MessageBox
   widgets.
2) do what Tkinter should have done, i.e. "Tkinter._default_root==None"
   but only do this after you have destroyed the root window with something
   like "rootWindow.destroy()", the latter is done automatically upon
   pressing the root-window-close-button, but has to be programmed otherwise.

Hope this helps, and sure hope it's correct:}

-- 
groetjes, carel




More information about the Python-list mailing list