Reputation: 35
I just started to work with tkinter and I'm still trying to get used to how it works. I was trying to prepare some sort of grid menu with 4 sections.
There is one frame at the top with the title of the app, one frame on the left with some buttons to configure the app and then, 4 equally sized frames in the rest.
My main issue here is the blank column between the left frame and the other four, how can I adjust this so the 4 squares fill in that space?
See below the code:
import datetime
import tkinter as tk
from time import strftime
window = tk.Tk()
window.geometry("1400x800")
window.configure(bg="white")
window.rowconfigure(20,weight=1)
window.columnconfigure(35,weight=1)
window.title("Hello World App")
entry_var_server = tk.StringVar(window,"")
entry_var_db = tk.StringVar(window,"")
entry_var_driver = tk.StringVar(window,"")
def window_widgets():
db_ini_frame_top = tk.Frame(master=window,bg="#57b956",height=120,width=1400,highlightbackground="black",highlightthickness=2)
db_ini_frame_top.grid(rowspan=3,columnspan=34,sticky="w")
db_ini_label_top = tk.Label(master=window,text="Hello World",bg="#57b956")
db_ini_label_top.configure(font=("Calibri",26))
db_ini_label_top.grid(row=1,column=18,sticky="n")
def cur_date(dic = {'01':'st','21':'st','31':'st',
'02':'nd','22':'nd',
'03':'rd','23':'rd'}):
x = strftime('%A, %B %d')
return x + dic.get(x[-2:],'th')+strftime(" %G - %H:%M")
date = cur_date()
db_ini_date = tk.Label(master=window,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,sticky="w")
db_ini_frame_left = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_frame_left.grid(row=3,rowspan=16,columnspan=2,sticky="w")
db_ini_frame_center_nw = tk.Frame(master=window,height=350,width=640,bg="blue")
db_ini_frame_center_nw.grid(row=3,column=3,columnspan=16,rowspan=12,sticky="nw")
db_ini_frame_center_sw = tk.Frame(master=window,height=450,width=640,bg="light blue")
db_ini_frame_center_sw.grid(row=12,column=3,columnspan=16,rowspan=12,sticky="sw")
db_ini_frame_center_ne = tk.Frame(master=window,height=350,width=640,bg="light blue")
db_ini_frame_center_ne.grid(row=3,column=19,columnspan=16,rowspan=12,sticky="ne")
db_ini_frame_center_se = tk.Frame(master=window,height=450,width=640,bg="blue")
db_ini_frame_center_se.grid(row=12,column=19,columnspan=16,rowspan=12,sticky="se")
window_widgets()
window.tk.mainloop()
Upvotes: 1
Views: 2340
Reputation: 385980
While we can fix your code with just a couple of small changes, taking a few minutes to create a smarter layout will make it much easier to modify your code as the application grows.
I'm going to offer some advice about how I would reorganize your code. At the end of the answer is a final working example. 90% of it is your original code, but with a few tweaks here and there to make creating the UI easier.
grid
for everythingFirst, I recommend that you not use grid
for everything. It's good for creating grids, but there are sometimes better ways to lay out an entire window. Divide your UI into logical groupings, and then lay them out using those groupings.
By organizing your UI into sections it makes it much easier to modify just a single section. When you use grid
for everything, making one small change might require you to change a dozen lines of code where you have to adjust row and column numbers, and row and column spans for everything just to accommodate a single new widget.
I also recommend that you group your calls to grid
and pack
together rather than sprinkling them throughout the code. I find it makes it much easier to visualize the layout, and easier to make changes since all related changes are close to each other rather than spread out.
You clearly have three distinct areas: a title across the top, some buttons on the left, and then everything else. So, start by creating just that. pack
is arguably the best choice when you have things arranged along the sides of a space.
So, start out by creating frames for those three areas. You can then use pack
to align them along the edges per your description.
db_ini_frame_top = tk.Frame(master=window, ...)
db_ini_frame_left = tk.Frame(master=window, ...)
db_ini_main = tk.Frame(master=window, ...)
db_ini_frame_top.pack(side="top", fill="x")
db_ini_frame_left.pack(side="left", fill="y")
db_ini_main.pack(side="top", fill="both", expand=True)
Even though you created a frame at the top, you were putting the label and date in the root window. You should be placing them inside the frame. When you get around to adding buttons, they should go in the left frame. And finally, for the other four windows, they need to go in the third frame.
db_ini_label_top = tk.Label(master=db_ini_frame_top, ...)
db_ini_date = tk.Label(master=db_ini_frame_top, ...)
db_ini_frame_center_nw = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_sw = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_ne = tk.Frame(master=db_ini_main, ...)
db_ini_frame_center_se = tk.Frame(master=db_ini_main, ...)
grid
for the four frames that are actually in a gridWhen using grid
, a rule of thumb is that you should give at least one row and one column a weight so that grid
knows what to do with extra space as the window grows or shrinks. In your case you want all four cells to be equal, so you should give them all an equal weight.
Because you now are using grid only for these four windows instead of trying to force everything into a single grid, you can use row and column numbers that make sense (ie: rows 0 and 1, columns 0 and 1, instead of artificially large rows and columns and spans).
db_ini_frame_center_nw = tk.Frame(master=db_ini_main,height=350,width=640,bg="blue")
db_ini_frame_center_sw = tk.Frame(master=db_ini_main,height=450,width=640,bg="light blue")
db_ini_frame_center_ne = tk.Frame(master=db_ini_main,height=350,width=640,bg="light blue")
db_ini_frame_center_se = tk.Frame(master=db_ini_main,height=450,width=640,bg="blue")
db_ini_main.grid_rowconfigure((0,1), weight=1)
db_ini_main.grid_columnconfigure((0,1), weight=1)
db_ini_frame_center_nw.grid(row=0,column=0, sticky="nsew")
db_ini_frame_center_sw.grid(row=0,column=1, sticky="nsew")
db_ini_frame_center_ne.grid(row=1,column=0, sticky="nsew")
db_ini_frame_center_se.grid(row=1,column=1, sticky="nsew")
This is what your full code looks like. I didn't adjust the location of the text in the title area, but it's easy to change it without affecting the other areas of the GUI.
Also, notice that you can manually resize the window and everything grows or shrinks appropriately rather than leaving empty spots.
import datetime
import tkinter as tk
from time import strftime
window = tk.Tk()
window.geometry("1400x800")
window.configure(bg="white")
window.rowconfigure(20,weight=1)
window.columnconfigure(35,weight=1)
window.title("Hello World App")
entry_var_server = tk.StringVar(window,"")
entry_var_db = tk.StringVar(window,"")
entry_var_driver = tk.StringVar(window,"")
def window_widgets():
db_ini_frame_top = tk.Frame(master=window,bg="#57b956",height=120,width=1400,highlightbackground="black",highlightthickness=2)
db_ini_frame_left = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_main = tk.Frame(master=window,bg="light grey",height=800,width=120,colormap="new",highlightbackground="black",highlightthickness=2)
db_ini_frame_top.pack(side="top", fill="x")
db_ini_frame_left.pack(side="left", fill="y")
db_ini_main.pack(side="top", fill="both", expand=True)
db_ini_label_top = tk.Label(master=db_ini_frame_top,text="Hello World",bg="#57b956")
db_ini_label_top.configure(font=("Calibri",26))
db_ini_label_top.grid(row=1,column=18,sticky="n")
def cur_date(dic = {'01':'st','21':'st','31':'st',
'02':'nd','22':'nd',
'03':'rd','23':'rd'}):
x = strftime('%A, %B %d')
return x + dic.get(x[-2:],'th')+strftime(" %G - %H:%M")
date = cur_date()
db_ini_date = tk.Label(master=db_ini_frame_top,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,sticky="w")
db_ini_frame_center_nw = tk.Frame(master=db_ini_main,height=350,width=640,bg="blue")
db_ini_frame_center_sw = tk.Frame(master=db_ini_main,height=450,width=640,bg="light blue")
db_ini_frame_center_ne = tk.Frame(master=db_ini_main,height=350,width=640,bg="light blue")
db_ini_frame_center_se = tk.Frame(master=db_ini_main,height=450,width=640,bg="blue")
db_ini_main.grid_rowconfigure((0,1), weight=1)
db_ini_main.grid_columnconfigure((0,1), weight=1)
db_ini_frame_center_nw.grid(row=0,column=0, sticky="nsew")
db_ini_frame_center_sw.grid(row=0,column=1, sticky="nsew")
db_ini_frame_center_ne.grid(row=1,column=0, sticky="nsew")
db_ini_frame_center_se.grid(row=1,column=1, sticky="nsew")
window_widgets()
window.tk.mainloop()
Upvotes: 2
Reputation: 11342
The date field is in a single column so it is pushing the the next column to the right.
Update your date block and add columnspan=4
date = cur_date()
db_ini_date = tk.Label(master=window,text=date,bg="#57b956")
db_ini_date.configure(font=("Calibri",12))
db_ini_date.grid(row=0,column=0,columnspan=4,sticky="w") # Allow 4 columns for date
Output
Upvotes: 0