garlic
garlic

Reputation: 197

Grid method to position frames properly

I'm trying to use the grid() method to position two frames - one at the top of the window, and one on the left of the window.

I've been successful in doing that with the pack() method - so this is getting me what I want:

It looks fine with the pack method

This works with the pack() method, which works great:

import tkinter as tk

main_window = tk.Tk()
main_window.geometry("480x420")

frame_top = tk.Frame(main_window, bg="yellow", height=50)
frame_left = tk.Frame(main_window, bg="orange", width=50)

frame_top.pack(side=tk.TOP, fill=tk.X)
frame_left.pack(side=tk.LEFT, fill=tk.Y)


main_window.mainloop()

However, I'm trying to learn more about the grid method, so when I attempt to do the same thing with the grid() method, it ends up looking like this:

does not look right when I use the grid method

My code with the grid() method (something is wrong here):

import tkinter as tk

main_window = tk.Tk()
main_window.geometry("480x420")

frame_top = tk.Frame(main_window, bg="yellow", height=50)
frame_left = tk.Frame(main_window, bg="orange", width=50)

frame_top.grid(row=0, column=0, sticky=tk.W+tk.N+tk.E)
frame_left.grid(row=1, column=0, sticky=tk.W+tk.S+tk.N)


main_window.mainloop()

What am I doing wrong with the grid method? How can I make it end up looking the same way it does when I use pack()?

Upvotes: 0

Views: 123

Answers (2)

Bryan Oakley
Bryan Oakley

Reputation: 385910

By default, grid won't allocate any extra space to a widget unless told to do so. Since your widgets aren't very wide, there's a lot of unused extra space.

You can tell grid what to do with the extra space by giving rows and columns "weight". The weight tells grid how to allocate extra space. A good rule of thumb is that you should always give at least one row and one column a weight for every widget that uses grid to manage its children.

In your specific case, adding the following code will give you the same appearance as the one where you use pack:

main_window.grid_rowconfigure(1, weight=1)
main_window.grid_columnconfigure(0, weight=1)

This tells grid that any extra vertical space should be given to row 1, and any extra horizontal space should go to column 0

However, that's just a quick hack to illustrate. I'm guessing you're going to want to put other widgets in the large white space. If that's the case, I think the better solution to give all of the weight to row 1 and column 1. Then, make sure that the yellow frame is told to span two columns. I also recommend nearly always having widgets be "sticky" to all sides. Otherwise, you may end up with white space that you don't want.

frame_top.grid(row=0, column=0, sticky="nsew", columnspan=2)
frame_left.grid(row=1, column=0, sticky="nsew")

main_window.grid_rowconfigure(1, weight=1)
main_window.grid_columnconfigure(1, weight=1)

The next step would be to put a frame in row 1, column 1. You can then add widgets into this frame without affecting the main layout -- inside the frame you can use pack or grid and that layout will be independent of the layout in the window as a whole.

Upvotes: 1

jizhihaoSAMA
jizhihaoSAMA

Reputation: 12672

Only use .grid() can not do it directly. You need to set the rowspan and columnspan(If you want it always full one row or one column). And set columnconfigure and rowconfigure to make it responsive.It is a little complex.

import tkinter as tk

main_window = tk.Tk()
main_window.geometry("480x420")

frame_top = tk.Frame(main_window, bg="yellow", height=50)
frame_left = tk.Frame(main_window, bg="orange", width=50)

# always full one row
frame_top.grid(row=0, column=0, columnspan=999, sticky=tk.W+tk.N+tk.E)
# always full one column
frame_left.grid(row=1, column=0, rowspan=999, sticky=tk.W+tk.S+tk.N)

# make it responsive
main_window.grid_rowconfigure(0,weight=0)
main_window.grid_rowconfigure(1,weight=1)
main_window.grid_columnconfigure(0,weight=0)
main_window.grid_columnconfigure(1,weight=1)

main_window.mainloop()

Now it is: enter image description here

Upvotes: 1

Related Questions