I want to create simple gui in tkinter that consist of notebook frame and several frames inside of each tabs. Let's say I want 2 labeled frames inside each of notebook's tabs spanning 100% of window width and 50% of window height.
I will have more frames/elements inside that I want to take x% of the window widht/height.
I read that tkinter gui should resize automatically when window is resized, but I cannot get it to work.
I cannot figure out how to do it with grid layout manager and documentation says it should be used over pack.
Example of my code:
import tkinter as tk
from tkinter import ttk, Tk
root = Tk()
root.geometry('1200x800')
root.title("Test")
tab_frame = ttk.Notebook(root)
tab_frame.grid()
####### change Notebook size in case main window changes
def conf(event):
tab_frame.config(height=root.winfo_height(), width=root.winfo_width())
# without this you cannot resize frames of the notebook by grid(sticky) or width/height !
return
root.bind("<Configure>",conf)
#######
s1 = ttk.Style()
s1.configure('test_red.TFrame', background='red')
s2 = ttk.Style()
s2.configure('test_green.TFrame', background='green')
s3 = ttk.Style()
s3.configure('test_blue.TFrame', background='blue')
tab1 = ttk.Frame(tab_frame, height=100, width=100, style='test_red.TFrame')
tab1.grid()
tab2 = ttk.Frame(tab_frame, height=100, width=100, style='test_blue.TFrame')
tab2.grid()
tab_frame.add(tab1, text='Tab1')
tab_frame.add(tab2, text='Tab2')
### frames in tab
label_frame1 = ttk.Labelframe(tab1, text='Label1', width=100, height=100, style='test_green.TFrame')
label_frame1.grid()
#label_frame.grid(sticky='e') # sticky does not work in any combination
label_frame2 = ttk.Labelframe(tab1, text='Label2', width=100, height=100, style='test_blue.TFrame')
label_frame2.grid()
root.mainloop()
First you can use tab_frame.pack(fill="both", expand=1)
instead of .grid()
and then you don't need to bind <Configure>
event to resize tab_frame
.
Second you can use rowconfigure()
and columnconfigure()
to make the two LabelFrame
s to fill horizontally and vertically.
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry('1200x800')
root.title("Test")
tab_frame = ttk.Notebook(root)
tab_frame.pack(fill="both", expand=1) # used pack() instead of grid()
s = ttk.Style()
s.configure('test_red.TFrame', background='red')
s.configure('test_green.TFrame', background='green')
s.configure('test_blue.TFrame', background='blue')
tab1 = ttk.Frame(tab_frame, style='test_red.TFrame')
tab2 = ttk.Frame(tab_frame, style='test_blue.TFrame')
tab_frame.add(tab1, text='Tab1')
tab_frame.add(tab2, text='Tab2')
# make two LabelFrames to fill horizontally
tab1.columnconfigure(0, weight=1)
# make two LabelFrames to evenly fill vertically
tab1.rowconfigure((0,1), weight=1)
### frames in tab
label_frame1 = ttk.Labelframe(tab1, text='Label1', style='test_green.TFrame')
label_frame1.grid(sticky="nsew")
label_frame2 = ttk.Labelframe(tab1, text='Label2', style='test_blue.TFrame')
label_frame2.grid(sticky="nsew")
root.mainloop()
You can use place()
on the two LabelFrames to achieve same goal:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry('1200x800')
root.title("Test")
tab_frame = ttk.Notebook(root)
tab_frame.pack(fill="both", expand=1) # used pack() instead of grid()
s = ttk.Style()
s.configure('test_red.TFrame', background='red')
s.configure('test_green.TFrame', background='green')
s.configure('test_blue.TFrame', background='blue')
tab1 = ttk.Frame(tab_frame, style='test_red.TFrame')
tab2 = ttk.Frame(tab_frame, style='test_blue.TFrame')
tab_frame.add(tab1, text='Tab1')
tab_frame.add(tab2, text='Tab2')
### frames in tab
label_frame1 = ttk.Labelframe(tab1, text='Label1', style='test_green.TFrame')
label_frame1.place(x=0, y=0, relwidth=1, relheight=0.5)
label_frame2 = ttk.Labelframe(tab1, text='Label2', style='test_blue.TFrame')
label_frame2.place(x=0, rely=0.5, relwidth=1, relheight=0.5)
root.mainloop()