How to position labels using the grid method in python tkinter?

9.6k Views Asked by At

Im trying to put a large label at the top of the window in the middle, then 3 Option menus evenly spaced out below it. I can't get the menus to span across the entire window. I'm not sure if what I'm doing wrong is having

root.geometry("800x600")

at the bottom. Everything is evenly spaced but it's all pushed to the left side of the window, instead of filling the whole thing. I haven't gotten to the next part where I will be binding functions that will display paragraphs of text underneath each of the menus, which is why I want the window so big.

here is my code:

from tkinter import *
from tkinter import messagebox

root=Tk()

topFrame=Frame(root)
bottomFrame=Frame(root)

#The first label
lbl=Label(root,text="Pick a Decade",bg="turquoise",fg="hot pink",font=  ("Times","40","bold italic"))
lbl.grid(row=1,column=1)

#Functions
def fifties(s):
    if s=="Intro":
    lbl=Label(root,text="1950's intro",bg="turquoise")
    lbl.grid(column=1)
if s=="Political":
    lbl=Label(root,text="1950's politcal",bg="turquoise")
    lbl.grid(column=1)
if s=="Economic":
    lbl=Label(root,text="1950's economic",bg="turquoise")
    lbl.grid(column=1)
if s=="Social":
    lbl=Label(root,text="1950's social",bg="turquoise")
    lbl.grid(column=1)
if s=="Technological":
    lbl=Label(root,text="1950's technological",bg="turquoise")
    lbl.grid(column=1)
if s=="Aesthetic":
    lbl=Label(root,text="1950's aesthetic",bg="turquoise")
    lbl.grid(column=1)

def sixties(s):
if s=="Intro":
    lbl=Label(root,text="1960's intro")
    lbl.grid(column=1,row=3)
if s=="Political":
    lbl=Label(root,text="1960's politcal")
    lbl.grid(column=1,row=3)
if s=="Economic":
    lbl=Label(root,text="1960's economic")
    lbl.grid(column=1,row=3)
if s=="Social":
    lbl=Label(root,text="1960's social")
    lbl.grid(column=1,row=3)
if s=="Technological":
    lbl=Label(root,text="1960's technological")
    lbl.grid(column=1,row=3)
if s=="Aesthetic":
    lbl=Label(root,text="1960's aesthetic")
    lbl.grid(column=1,row=3)

def seventies(s):
if s=="Intro":
    lbl=Label(root,text="1970's intro")
    lbl.grid(column=2,row=3)
if s=="Political":
    lbl=Label(root,text="1970's political")
    lbl.grid(column=2,row=3)
if s=="Economic":
    lbl=Label(root,text="1970's economic")
    lbl.grid(column=2,row=3)
if s=="Social":
    lbl=Label(root,text="1970's social")
    lbl.grid(column=2,row=3)
if s=="Technological":
    lbl=Label(root,text="1970's technological")
    lbl.grid(column=2,row=3)
if s=="Aesthetic":
    lbl=Label(root,text="1970's aesthetic")
    lbl.grid(column=2,row=3)

#Menus
v=StringVar(root)
v.set("1950's")
a=OptionMenu(root,v,"Intro","Political","Economic","Social","Technological","Aesthetic",command=fifties)
a.grid(column=0,row=2)

v=StringVar(root)
v.set("1960's")
a=OptionMenu(root,v,"Intro","Political","Economic","Social","Technological","Aesthetic",command=sixties)
a.grid(column=1,row=2)

v=StringVar(root)
v.set("1970's")
a=OptionMenu(root,v,"Intro","Political","Economic","Social","Technological","Aesthetic",command=seventies)
a.grid(column=2,row=2)


#Root
root.configure(background="turquoise")
root.geometry("800x600")
root.mainloop()

The labels inside the functions that say "1950's social" etc. etc. are going to be the large paragraphs.

2

There are 2 best solutions below

0
On

As default cells in grid have no size. You can only set minimal size using

root.columnconfigure(0, minsize=300)
root.columnconfigure(1, minsize=300)
root.columnconfigure(2, minsize=300)

To create big header you can connect 3 cells

lbl.grid(..., columnspan=3)

You can also use widget to cell size using sticky='we'

grid(..., sticky='we')

w = west/left, e = east/right

Working example:

import tkinter as tk

# --- functions ---

def fifties(selection):
    data = {
        "Intro": "1950's intro",
        "Political": "1950's politcal",
        "Economic": "1950's economic",
        "Social": "1950's social", 
        "Technological": "1950's technological",
        "Aesthetic": "1950's aesthetic",
    }

    if selection in data:
        text_1950['text'] = data[selection]
    else:
        text_1950['text'] = "Unknow selection: " + selection 

def sixties(selection):
    data = {
        "Intro": "1960's intro",
        "Political": "1960's politcal",
        "Economic": "1960's economic",
        "Social": "1960's social", 
        "Technological": "1960's technological",
        "Aesthetic": "1960's aesthetic",
    }

    if selection in data:
        text_1960['text'] = data[selection]
    else:
        text_1960['text'] = "Unknow selection: " + selection

def seventies(selection):
    data = {
        "Intro": "1970's intro",
        "Political": "1970's politcal",
        "Economic": "1970's economic",
        "Social": "1970's social", 
        "Technological": "1970's technological",
        "Aesthetic": "1970's aesthetic",
    }

    if selection in data:
        text_1970['text'] = data[selection]
    else:
        text_1970['text'] = "Unknow selection: " + selection

# --- main ---

# - init -
root = tk.Tk()
root.configure(bg="turquoise")
root.geometry("900x600")

# - set columns minimal size -

root.columnconfigure(0, minsize=300)
root.columnconfigure(1, minsize=300)
root.columnconfigure(2, minsize=300)

# - header -

lbl = tk.Label(root, text="Pick a Decade", bg="turquoise", fg="hot pink", font=("Times", 40, "bold italic"))
lbl.grid(column=0, row=0, columnspan=3, sticky='we')

# - menus -

options = ["Intro", "Political", "Economic", "Social", "Technological", "Aesthetic"]

var = tk.StringVar(value="1950's")
a = tk.OptionMenu(root, var, *options, command=fifties)
a.grid(column=0, row=2, sticky='we')

var = tk.StringVar(value="1960's")
a = tk.OptionMenu(root, var, *options, command=sixties)
a.grid(column=1, row=2, sticky='we')

var = tk.StringVar(value="1970's")
a = tk.OptionMenu(root, var, *options, command=seventies)
a.grid(column=2, row=2, sticky='we')

# - empty labels for text -

text_1950 = tk.Label(root, bg="turquoise")
text_1950.grid(column=0, row=3)

text_1960 = tk.Label(root, bg="turquoise")
text_1960.grid(column=1, row=3)

text_1970 = tk.Label(root, bg="turquoise")
text_1970.grid(column=2, row=3)

# - start -
root.mainloop()

enter image description here

0
On

The grid geometry manager needs to know what to do if there's more space than necessary to display the widgets. It does this by allocating the extra space relative to the "weight" of each row and column. For example, if one column has a weight of 3 and another column has a weight of 1, the first column will be given 3 times the amount of extra space as the other column.

By default, rows and columns have a weight of zero. That means if there is extra space -- as in your example -- it goes unused.

The absolute simplest solution to your problem is to give each column an equal non-zero weight so that extra space is evenly distributed. You do that with the columnconfigure (or grid_columnconfigure) method:

root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)

Since you say you want the label to span all three columns, you need to tell grid that, which you can do by placing the label in column zero and giving it a columnspan of 3:

lbl.grid(row=1,column=0, columnspan=3)