I am now practicing how dynamic the frame setting can be in tkinter.
For pure frame setting, it looks perfect:
import tkinter as tk
class MyWindow:
def __init__(self, root):
w_root = 1280
h_root = 720
root.title('My model')
root.geometry(f"{w_root}x{h_root}")
self.top_frame = tk.Frame(root, width=w_root, height=80, bg='grey')
self.top_frame.grid(row=0, column=0, padx=0, pady=5)
self.main_frame = tk.Frame(root, width=w_root, height=640, bg='blue')
self.main_frame.grid(row=1, column=0, padx=0, pady=0)
self.left_frame = tk.Frame(self.main_frame, width=500, height=620, bg='red')
self.left_frame.grid(row=0, column=0, padx=5, pady=5)
self.right_frame = tk.Frame(self.main_frame, width=760, height=620, bg='yellow')
self.right_frame.grid(row=0, column=1, padx=5, pady=5)
root = tk.Tk()
mywin = MyWindow(root)
root.mainloop()
However, when I tried to put a label in left_frame (frame inside main frame), the interface became strange:
import tkinter as tk
class MyWindow:
def __init__(self, root):
w_root = 1280
h_root = 720
root.title('My model')
root.geometry(f"{w_root}x{h_root}")
self.top_frame = tk.Frame(root, width=w_root, height=80, bg='grey')
self.top_frame.grid(row=0, column=0, padx=0, pady=5)
self.main_frame = tk.Frame(root, width=w_root, height=640, bg='blue')
self.main_frame.grid(row=1, column=0, padx=0, pady=0)
self.left_frame = tk.Frame(self.main_frame, width=500, height=620, bg='red')
self.left_frame.grid(row=0, column=0, padx=5, pady=5)
self.right_frame = tk.Frame(self.main_frame, width=760, height=620, bg='yellow')
self.right_frame.grid(row=0, column=1, padx=5, pady=5)
self.lb_currdate = tk.Label(self.left_frame, text='my lable1:')
self.lb_currdate.config(font=('Arial', 9))
self.lb_currdate.grid(row=0,column=0, padx=5, pady=5)
self.ent_currdate = tk.Entry(self.left_frame)
self.ent_currdate.insert(tk.END, str(0))
self.ent_currdate.grid(row=0,column=1, padx=5, pady=5)
root = tk.Tk()
mywin = MyWindow(root)
root.mainloop()
I would expect the frames look the same and the label and entry will displace on top of red frame (left frame).
I am so confused about this, could someone give me a hint which line of codes are wrong?
Thank you
#-----Update------
Based on the suggestion, I included sticky in my grid. It looks much better but still not 100% as what I expected. I try different combination of sticky, but none of them is correct:
Test1 (give left frame sticky):
self.left_frame.grid(row=0, column=0, padx=5, pady=5, sticky=tk.N tk.E tk.S tk.W)
the mainframe doesn't filled enti
Test2 (give left frame and main frame both sticky):
self.main_frame.grid(row=1, column=0, padx=0, pady=0, sticky=tk.N tk.E tk.S tk.W)
self.left_frame.grid(row=0, column=0, padx=5, pady=5, sticky=tk.N tk.E tk.S tk.W)
left frame and right frame doesn't fill the main frame
CodePudding user response:
Making the red frame expand to fill its grid cell
The problem is that the frame automatically resizes to fit the content. To fix this, you can use the sticky
keyword argument of the grid
method.
self.left_frame.grid(row=0, column=0, padx=5, pady=5, sticky='NESW')
The 'NESW'
stands for "north, east, south, west". If you prefer, you can write this as:
self.left_frame.grid(row=0, column=0, padx=5, pady=5, sticky=tk.N tk.E tk.S tk.W)
You will need to do this for every frame that you want to behave like this.
You can also use different sticky values to produce different outcomes, e.g. if you just use sticky=tk.S
then the frame will move to the bottom of its available space.
Removing unwanted empty space
In order to make the frames fill the space, you can use grid_rowconfigure
and grid_columnconfigure
with the weight
keyword argument. See here for a full explaintion.
In short, you need to configure the grid to expand to fill the available space rather than manually specifying widths and heights. I have modified your code to do this. Note that the only time the height is specified in pixels is when the frame is not supposed to expand, namely for the top_frame
.
import tkinter as tk
class MyWindow:
def __init__(self, root: tk.Tk):
w_root = 1280
h_root = 720
root.title('My model')
root.geometry(f"{w_root}x{h_root}")
self.top_frame = tk.Frame(root, height=80, bg='grey')
self.top_frame.grid(row=0, column=0, padx=0, pady=5, sticky=tk.N tk.E tk.S tk.W)
self.main_frame = tk.Frame(root, bg='blue')
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=1)
self.main_frame.grid(row=1, column=0, padx=0, pady=0, sticky=tk.N tk.E tk.S tk.W)
self.main_frame.grid_rowconfigure(0, weight=1)
self.left_frame = tk.Frame(self.main_frame, bg='red')
self.left_frame.grid(row=0, column=0, padx=5, pady=5, sticky=tk.N tk.E tk.S tk.W)
self.main_frame.grid_columnconfigure(0, weight=1)
self.right_frame = tk.Frame(self.main_frame, bg='yellow')
self.right_frame.grid(row=0, column=1, padx=5, pady=5, sticky=tk.N tk.E tk.S tk.W)
self.main_frame.grid_columnconfigure(1, weight=2)
self.lb_currdate = tk.Label(self.left_frame, text='my lable1:')
self.lb_currdate.config(font=('Arial', 9))
self.lb_currdate.grid(row=0, column=0, padx=5, pady=5)
self.ent_currdate = tk.Entry(self.left_frame)
self.ent_currdate.insert(tk.END, str(0))
self.ent_currdate.grid(row=0, column=1, padx=5, pady=5, sticky=tk.N tk.E tk.S tk.W)
self.left_frame.grid_columnconfigure(1, weight=1)
root = tk.Tk()
mywin = MyWindow(root)
root.mainloop()