2
votes

I guess I am not understanding something about the way Grid works...

My question seems related to this SO question: Python tkinter Text widget fill fixed sized frame using grid

To which the answer was that weight needed to be given to an item in order have it take up the extra space, using the functions grid_columnconfigure() and grid_rowconfigure().

Below is the code for a simple example. What I am trying to achieve is to be able to specify the size of frame0, have it be stuck to all sides of the root window, and then have the child frame, frame1 be stuck to frame0 on left, top, right, and to stretch/shrink when the main window of the app is resized.

So, initially, I would expect the application to launch at basically 500x350 size. frame1 would be as high as it naturally is and basically 500 pixels wide (minus a little for padding).

After acw1668's comment, I updated the code to configure root and set it's weight to 1. The size of Entry now varies to take up any horizontal space, just as I wanted. But the GUI still launches at "natural" size, though I have given an explicit size to frame0. I'm not understanding why the geometry manager does not treat 500x350 as the natural size and allocate that?

Can anybody see how to get the initial launch sized as expected?

#!/usr/bin/env python3

from tkinter import *
from tkinter import ttk

root = Tk()
root.title("Layout Problem")
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)

frame0 = ttk.Frame(root, padding=4, width=500, height=350)
frame0.grid_columnconfigure(0, weight=1)
frame0.grid_rowconfigure(0, weight=1)
frame0.grid(column=0, row=0, sticky=(W, N, E, S))

frame1 = ttk.Frame(frame0, padding=4)
frame1.grid_columnconfigure(1, weight=1)
frame1['borderwidth'] = 2
frame1['relief'] = "ridge"
frame1.grid(column=0, row=0, sticky=(W, N, E))

# add widgets to 'frame1'
ttk.Label(frame1, text="Label: ").grid(row=0, column=0, sticky=W)

entryValue = StringVar()
ttk.Entry(frame1, textvariable=entryValue)\
    .grid(row=0, column=1, sticky=(W, E))
entryValue.set("Entry")

ttk.Button(frame1, text="Button")\
    .grid(row=0, column=2, sticky=E)

root.mainloop()
1
That first link doesn't link to a question, it links to a search result. It's unclear which question you're talking about. You can get a link to the actual question from the share link below the list of tags.Bryan Oakley
Why do you want to force the frame to a specific size? That's fairly unusual. Also, is there a reason you're only using grid? For the layout you're trying to achieve, it seems that pack might be the better solution.Bryan Oakley
Note that grid_rowconfigure() and grid_columnconfigure() should be applied on the parent container to control the layout of its chidren. So you should call root.grid_rowconfigure() and root.grid_columnconfigure() to control frame0. Similarly you should call frame0.grid_columnconfigure() to control frame1.acw1668
Bryan, thank you for your responses. I updated the link to point to the proper answer - my bad, thanks for pointing that out. As for why I want to do what I am trying to do, I am a Tkinter noob and trying to learn. I'm following examples in "Modern Tkinter Examples for Busy Python Developers" by Mark Roseman, found at: tkdocs.com He suggests to do everything with Grid.user1441004
Then you need to use root.grid_columnconfigure(0, weight=1, minsize=500) and root.grid_rowconfigure(0, weight=1, minsize=350).acw1668

1 Answers

0
votes

For reference, below is the code after incorporating acw1668's suggestions.

The GUI now launches at expected size. There is sort of a secondary issue in that now the frame doesn't shrink below 500 px width (i.e., the Entry will not collapse back to natural size) though you can force the application window to be smaller. That's sort of a separate issue.

I can see there is some subtlety to this whole layout and resizing business and I've yet got a ways to go. ;)

Hopefully this question will have some pedagogic value to others following the same trail:

#!/usr/bin/env python3

from tkinter import *
from tkinter import ttk

root = Tk()
root.title("Layout Problem")
root.grid_columnconfigure(0, weight=1, minsize=500)
root.grid_rowconfigure(0, weight=1, minsize=350)

frame0 = ttk.Frame(root, padding=4)
frame0.grid(column=0, row=0, sticky=(W, N, E, S))
frame0.grid_columnconfigure(0, weight=1)
frame0.grid_rowconfigure(0, weight=1)

frame1 = ttk.Frame(frame0, padding=4)
frame1.grid_columnconfigure(1, weight=1)
frame1['borderwidth'] = 2
frame1['relief'] = "ridge"
frame1.grid(column=0, row=0, sticky=(W, N, E))

# add widgets to 'frame1'
ttk.Label(frame1, text="Label: ").grid(row=0, column=0, sticky=W)

entryValue = StringVar()
ttk.Entry(frame1, textvariable=entryValue)\
    .grid(row=0, column=1, sticky=(W, E))
entryValue.set("Entry")

ttk.Button(frame1, text="Button")\
    .grid(row=0, column=2, sticky=E)

root.mainloop()