Tkinter protocol("WM_DELETE_WINDOW,...)

Chad Netzer cnetzer at mail.arc.nasa.gov
Thu May 8 15:01:31 EDT 2003


On Thu, 2003-05-08 at 08:43, Dave Hansen wrote:

> 
> This is a long tale of a problem I encountered, and I think I fixed,
> but I'm soliciting the opinions of those more experienced in such
> matters.  I don't want this biting me again...

> 
> The Tkinter script keeps the same basic structure.  There are many
> kinds of nodes, but they basically all look something like this:
> 
>    class Node(Frame):
>       def __init__(self, <question, answers, results>):
>          <Build the node.  No Tkinter calls>

Why to you derive Node from Frame?  You are saying that each Node is-a
Frame, but then you are operating on them in a manner that is
inconsistent with the way Frames are handled (For example, when you
instantiate a Frame object, one normally assumes it is initialized.
I think you should instead try a has-a relationship.  Each Node has a
Frame which you can pack(), etc.

>       def ask(self):
>          Frame.__init__(self)
>          <Build and pack a frame for the user>

Again, if you end up doing a "self.pack()" anywhere in here, you are
certainly doing things in an odd manner (I won't go so far as to say
'wrong', but in my experience, such things always, always, ALWAYS lead
to problems.

>          self.result = Terminate        # Special flag
>          self.wait_window(self)

if each Node had a 'self.frame=Frame()', then you could do
'self.frame.wait_window()'


> Also note that no call to mainloop is made.  This is due to the way
> the script eveolved (text mode => Tkinter).

Bingo.  If you aren't running mainloop(), and you are still relying on
events to occur (window events, window manager events, etc.) then you
better have a REALLY good idea of how event processing works in Tkinter
(because you will have to do it yourself, using lots of update() calls)

The simple answer to this is, "Use mainloop()".  A lot of your problems
will magically disappear.

Now, you are perhaps asking yourself, "Well, how do I do my processing? 
I don't want to have to have a button that starts the processing, I just
want it to occur."

The answer is that you can use the after_idle() call to start up a
function when the mainloop() executes.  Call it before going into the
mainloop(), and it will execute your function.  The function can then
simply do all the work you need it to do.  I suspect that will at least
eliminate some of the need for the update() calls, and the "hangs".

ie.:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import Tkinter

def some_computing():
    print "Hello"

root = Tkinter.Tk()
root.after_idle( some_computing )
root.mainloop()


-- 

Chad Netzer
(any opinion expressed is my own and not NASA's or my employer's)






More information about the Python-list mailing list