There are other geometry managers: "pack" is also quite powerful, but harder to use and understand; "place" gives you complete control of positioning each element; we'll see even widgets like paned windows, notebooks, canvas and text can act as geometry managers.
Columns and Rows
Using grid, widgets are assigned a "column" number and a "row" number, which indicates their relative position to each other.
Column and row numbers must be integers, with the first column and row starting at 0.
Spanning Multiple Cells
Widgets can take up more than a single cell in the grid; to do this, you'll use the"columnspan"and"rowspan" options when gridding the widget.
from tkinter import *
from tkinter import ttk
root = Tk()
content = ttk.Frame(root)
frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100)
namelbl = ttk.Label(content, text="Name")
name = ttk.Entry(content)
onevar = BooleanVar()
twovar = BooleanVar()
threevar = BooleanVar()
onevar.set(True)
twovar.set(False)
threevar.set(True)
one = ttk.Checkbutton(content, text="One", variable=onevar, onvalue=True)
two = ttk.Checkbutton(content, text="Two", variable=twovar, onvalue=True)
three = ttk.Checkbutton(content, text="Three", variable=threevar, onvalue=True)
ok = ttk.Button(content, text="Okay")
cancel = ttk.Button(content, text="Cancel")
content.grid(column=0, row=0)
frame.grid(column=0, row=0, columnspan=3, rowspan=2)
namelbl.grid(column=3, row=0, columnspan=2)
name.grid(column=3, row=1, columnspan=2)
one.grid(column=0, row=3)
two.grid(column=1, row=3)
three.grid(column=2, row=3)
ok.grid(column=3, row=3)
cancel.grid(column=4, row=3)
root.mainloop()
Layout within the Cell
By default, if a cell is larger than the widget contained in it, the widget will be centered within it, both horizontally and vertically, with the master's background showing in the empty space around it. The"sticky" option can be used to change this default behavior.
The value of the "sticky" option is a string of 0 or more of the compass directions "nsew", specifying which edges of the cell the widget should be "stuck" to. So for example, avalue of"n" (north) will jam the widget up against the top side, with any extra vertical space on the bottom; the widget will still be centered horizontally. A value of"nw" (north-west)means the widget will be stuck to the top left corner, with extra space on the bottom and right.
Handling Resize
Padding
from tkinter import *
from tkinter import ttk
root = Tk()
content = ttk.Frame(root, padding=(3,3,12,12))
frame = ttk.Frame(content, borderwidth=5, relief="sunken", width=200, height=100)
namelbl = ttk.Label(content, text="Name")
name = ttk.Entry(content)
onevar = BooleanVar()
twovar = BooleanVar()
threevar = BooleanVar()
onevar.set(True)
twovar.set(False)
threevar.set(True)
one = ttk.Checkbutton(content, text="One", variable=onevar, onvalue=True)
two = ttk.Checkbutton(content, text="Two", variable=twovar, onvalue=True)
three = ttk.Checkbutton(content, text="Three", variable=threevar, onvalue=True)
ok = ttk.Button(content, text="Okay")
cancel = ttk.Button(content, text="Cancel")
content.grid(column=0, row=0, sticky=(N, S, E, W))
frame.grid(column=0, row=0, columnspan=3, rowspan=2, sticky=(N, S, E, W))
namelbl.grid(column=3, row=0, columnspan=2, sticky=(N, W), padx=5)
name.grid(column=3, row=1, columnspan=2, sticky=(N, E, W), pady=5, padx=5)
one.grid(column=0, row=3)
two.grid(column=1, row=3)
three.grid(column=2, row=3)
ok.grid(column=3, row=3)
cancel.grid(column=4, row=3)
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
content.columnconfigure(0, weight=3)
content.columnconfigure(1, weight=3)
content.columnconfigure(2, weight=3)
content.columnconfigure(3, weight=1)
content.columnconfigure(4, weight=1)
content.rowconfigure(1, weight=1)
root.mainloop()
Additional Grid Features
Querying and Changing Grid Options
The "slaves" method will tell you all the widgets that have been gridded inside a master, or optionally those within just a certain column or row. The"info" method will give you a list of all the grid options for a widget and their values. Finally, the"configure" method lets you change one or more grid options on a widget.
>>> content.grid_slaves()
<map object at 0x00C3F470>
>>> for w in content.grid_slaves(): print(w)
...
.14597008.14622128
.14597008.14622096
.14597008.14622064
.14597008.14622032
.14597008.14622000
.14597008.14621872
.14597008.14621840
.14597008.14621808
>>> for w in content.grid_slaves(row=3): print(w)
...
.14597008.14622128
.14597008.14622096
.14597008.14622064
.14597008.14622032
.14597008.14622000
>>> for w in content.grid_slaves(column=0): print(w)
...
.14597008.14622000
.14597008.14621808
>>> namelbl.grid_info()
{'rowspan': '1', 'column': '3', 'sticky': 'nw', 'ipady': '0', 'ipadx': '0', 'columnspan': '2',
'in': <tkinter.ttk.Frame object at 0x00DEBB90>, 'pady': '0', 'padx': '5', 'row': '0'}
>>> namelbl.grid_configure(sticky=(E,W))
>>> namelbl.grid_info()
{'rowspan': '1', 'column': '3', 'sticky': 'ew', 'ipady': '0', 'ipadx': '0', 'columnspan': '2',
'in': <tkinter.ttk.Frame object at 0x00DEBB90>, 'pady': '0', 'padx': '5', 'row': '0'}
Internal Padding
You saw how the "padx" and "pady" grid options added extra space around the outside of a widget.There's also a less used type of padding called "internal padding", which is controlled by thegrid options"ipadx" and"ipady".
Forget and Remove
The "forget" method of grid, taking as arguments a list of one or more slave widgets, can be used to remove slaves from the grid they're currently part of.