[Tutor] Re: Tkinter

Michael Lange klappnase at freenet.de
Tue Mar 9 06:16:46 EST 2004


On Mon, 8 Mar 2004 10:53:12 -0800 (PST)
Marilyn Davis <marilyn at deliberate.com> wrote:

Hi, Marilyn,


> I'm liking this form:
> ----------------
> #!/usr/bin/env python
> '''Hello World in a GUI using Tkinter'''
> 
> from Tkinter import *
> 
> class Hello(Tk):
>     def __init__(self):
>         Tk.__init__(self)
>         self.title('Hello World')
>   
> if __name__ == '__main__':
>     Hello().mainloop()
> ------------------
> Is this acceptible?
> 
> I'm confused about pack() and grid().  I understand that you 
> shouldn't pack and grid into the same container.  But can I
> not grid into a container that is packed into its container?
> 
>
> I'm surprised that the following doesn't work.  The Label in
> the Frame at the bottom doesn't show up.
> 
> Are constrained to use the same geometry manager throughout an
> application?  Or am I making some other mistake?
> 

You've understood it right, you can use pack() and grid() within different
Frames inside the same window, but NEVER inside the same Frame.


> --------
> 
> #!/usr/bin/python
> from Tkinter import *
> 
> class Hello(Tk):
>     def __init__(self):
>         Tk.__init__(self)
>         self.title("Hello World")
>         self.geometry("150x100")   #width x height
>         
>         Label(self, text="Hello World").pack(side=LEFT)
> 
>         b = Button(self, text="Bye", command=self.destroy)
>         b.pack(side=RIGHT)
>        
>         f = Frame(self)
>         f.pack()
>         Label(f, text='Frame').grid()
> 
> if __name__ == '__main__':
>     Hello().mainloop()
>         
> --------
> 
> Thank you again for the valuable help.
> 
> Marilyn Davis
> 

I tried your example and the Label *did* show up, but not at the bottom
of the window but at the top and not completely (just "Fram" instead of "Frame").
If I enlarged the window it was completely there.
The problem here is obviously an inappropriate use of pack().
Generally, for the kind of window layout I think you intended, I'd recommend
the use of grid() instead of pack(), because grid makes it very easy to arrange
widgets in any number of rows and columns, with pack() you will find that it is often
necessary to create extra Frames to arrange your widgets like you wanted.

I changed your code a little:

-----------
#!/usr/bin/python
from Tkinter import *

class Hello(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.title("Hello World")
        self.geometry("150x100")   #width x height
        
        Label(self, text="Hello World").grid(row=0, column=0)

        b = Button(self, text="Bye", command=self.destroy)
        b.grid(row=0, column=1)
       
        f = Frame(self)
        f.grid(row=1, column=0, columnspan=2)# the extra Frame here is in fact not really necessary
        Label(f, text='Frame').pack()

if __name__ == '__main__':
    Hello().mainloop()
-----------
I think this is probably what you intended.
The strength of pack() is that it is easier to use if you just want to
have one or two widgets inside a Frame and want to control which widget
expands and collapses when the window is resized.
A resizable Text widget instead of Label(f, text='Frame') at the bottom with pack():

Text(self).pack(fill='both', expand=1)

With grid() you would have to call grid_rowconfigure() and grid_columnconfigure() first:

self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1)
Text(self).grid(row=1, column=0, columnspan=2, sticky='news')

Pack() is also very handy if you want to put a number of widgets in the same Frame,
always in the same direction (I added the following to the example):

f2 = Frame(self)
f2.grid(row=2, column=0, columnspan=2)
for i in range(10):
    Label(f, text=str(i)).pack(side='left')

However pack() gets hard to use if you want more than one direction for your
widgets - it is hard to mix 'left', 'right', 'top' and 'bottom' (as in your example).
In general, grid() is more powerful on complex layouts than pack(), but pack() is
often easier to use for simple guis. If in doubt which to use I prefer grid(), because it
can handle anything pack() can, but not vice versa.

I hope this helps

Michael




More information about the Tutor mailing list