In the previous sections, we have introduced several Tkinter widget types, such as label, button, drop-down menu, etc. Meanwhile, we have also mentioned briefly how to layout these widgets in the program window. This is the key point that you will learn in this section - Tkinter’s geometry management methods.
Tkinter has three geometry management methods, that is,
place. Let’s go through them one by one.
pack Layout Method
pack method, as literally indicated, packs the widget to the window frame after it is created. We come across this layout method in the section Tkinter Label where all the
pack options are also listed.
We will show you how to layout widgets with
pack method (also its options). A few examples help to demonstrate the right configuration.
pack Layout - Relative Position
import tkinter as tk app = tk.Tk() app.geometry('300x200') buttonW = tk.Button(app, text="West", width=15) buttonW.pack(side='left') buttonE = tk.Button(app, text="East", width=15) buttonE.pack(side='right') app.mainloop()
Run the program, you will get a window like this,
As you can see,
buttonWest snaps to the left side of the window and
buttonEast snaps to the right side of the window. You can try to scale the size of the window below, but you will find that they will still cling to the sides of the window and the relative position will not change.
side has four options -
It places the widget on the
side of the window. As illustrated in the example,
buttonW is allocated on the left side of the window, because
buttonE is on the right side of the window, because
Now we have an interesting scenario, what happens if two widgets have the same
side property, how the layout will be?
Try to answer it yourself, or check it by running the following codes.
import tkinter as tk app = tk.Tk() app.geometry('300x200') buttonW = tk.Button(app, text="West", width=15) buttonW.pack(side='left') buttonE1 = tk.Button(app, text="East 1", width=15) buttonE1.pack(side='right') buttonE2 = tk.Button(app, text="East 2", width=15) buttonE2.pack(side='right') app.mainloop()
pack to Add Widget Internal and External Padding
In some cases, you need to add some padding inside or outside the widget so that there is less congestion between the widgets, and also between the widget text and the widget boundaries. Now, you need options as
import tkinter as tk app = tk.Tk() app.geometry('300x200') buttonW = tk.Button(app, text="West") buttonW.pack(side='left', ipadx=20, padx=30) buttonE = tk.Button(app, text="East") buttonE.pack(side='right', ipadx=20, padx=30) app.mainloop()
Both buttons add inner 20 units padding and outer 30 units in the
x, and the unit is pixel but not the width of one character.
pack Layout Filling in X, Y Direction
The following code implementation could automatically fill the widget dimension to the same width or the same height as the window, and when you zoom the window, the size of the control can automatically change with the size of the window.
import tkinter as tk app = tk.Tk() app.geometry('300x200') buttonX = tk.Button(app, text="Fill X", bg="red", height=5) buttonX.pack(fill='x') buttonY = tk.Button(app, text="Fill Y", bg="green", width=10) buttonY.pack(side='left', fill='y') app.mainloop()
buttonX will fill the width of the whole window. Similarly,
fill='y' will fill the height of the whole window, and meanwhile
fill='both' will fill both the width and height.
pack Layout Option
expand - Automatically Expand
fill= option will automatically fill the widget in
y direction when the window size is modified. Another similar requirement is how to automatically display all the contents if the widget includes multiple options, like a list?
import tkinter as tk import calendar app = tk.Tk() buttonX = tk.Button(app, text="Label ", bg="blue", height=5) buttonX.pack(fill='x') listboxA = tk.Listbox(app, width=10) listboxA.pack(fill='both', expand=1) for i in range(1,13): listboxA.insert(tk.END, calendar.month_name[i]) app.mainloop()
expand=1, the list box will list all the items, from
December as demonstrated in the above example.
expand is set to be
False, then the list box only shows the first 10 items by default. You need to use the mouse or direction keys to show the hidden items after the list box is selected.
expand=0 disables the list box to automatically show all items.
grid Layout Method
grid is another and also the most important layout geometry method. This is the one you should learn if you only want to learn one single method among all geometry managers.
grid is often used in dialog boxes, and you could place the widgets based on the position coordinates of the grid.
grid layout method could have stable relative positions of all widgets.
The following example will create a relatively complicated GUI compared to the above examples, which uses as many options of
grid as possible that will be explained in the next sections.
import tkinter as tk app = tk.Tk() labelWidth = tk.Label(app, text = "Width Ratio") labelWidth.grid(column=0, row=0, ipadx=5, pady=5, sticky=tk.W+tk.N) labelHeight = tk.Label(app, text = "Height Ratio") labelHeight.grid(column=0, row=1, ipadx=5, pady=5, sticky=tk.W+tk.S) entryWidth = tk.Entry(app, width=20) entryHeight = tk.Entry(app, width=20) entryWidth.grid(column=1, row=0, padx=10, pady=5, sticky=tk.N) entryHeight.grid(column=1, row=1, padx=10, pady=5, sticky=tk.S) resultButton = tk.Button(app, text = 'Get Result') resultButton.grid(column=0, row=2, pady=10, sticky=tk.W) logo = tk.PhotoImage(file='python.gif') labelLogo = tk.Label(app, image=logo) labelLogo.grid(row=0, column=2, columnspan=2, rowspan=2, sticky=tk.W+tk.E+tk.N+tk.S, padx=5, pady=5) app.mainloop()
labelWidth.grid(column=0, row=0, ipadx=5, pady=5, sticky=tk.W+tk.N)
Every widget shall be placed in the absolute cell in the
grid layout method. The cell coordinate is determined by
labelWidth widget is placed in the cell of position
(0, 0). The coordinate starts from the upper left corner of the window.
pady options are the same as those in
sticky determines how the widget sticks to the cell when the widget is smaller than the cell.
||stick to left|
||stick to right|
||stick to top|
||stick to bottom|
sticky option is center, that is
labelLogo.grid(row=0, column=2, columnspan=2, rowspan=2, sticky=tk.W+tk.E+tk.N+tk.S, padx=5, pady=5)
The cell coordinate of
(column=2, row=0) and the size of logo is relatively large, therefore it is allocated with cell size of
rowspan=2 means the widget has spans of two cells both in
Y directions starting from the position of the widget.
place method places the widget in an absolute or relative position in the window. We still use the same approach as above to introduce the options of this layout method.
import tkinter as tk app = tk.Tk() app.geometry('300x300') labelA = tk.Label(app, text = "Label (0, 0)", fg="blue", bg="#FF0") labelB = tk.Label(app, text = "Label (20, 20)", fg="green", bg="#300") labelC = tk.Label(app, text = "Label (40, 50)", fg="black", bg="#f03") labelD = tk.Label(app, text = "Label (0.5, 0.5)", fg="orange", bg="#0ff") labelA.place(x=0, y=0) labelB.place(x=20, y=20) labelC.place(x=40, y=50) labelD.place(relx=0.5, rely=0.5) app.mainloop()
place Absolute Position
labelA.place(x=0, y=0) labelB.place(x=20, y=20)
y= options in
place determines the absolute positions of the widget, which have the unit as pixel. For example,
lableB.place(x=20, y=20) means
labelB is placed in the coordinate of
place Relative Position
The drawback of the absolute position is that if there are other widgets in the window placed with relative positions, when the window is zoomed, the widget using the absolute position layout will possibly have the overlap with other widgets.
place layout method also has the relative position option, that is,
rely are in the range of
0.0~1.0. It is the relative percentage of the widget position to the window size.
relx=0.5, rely=0.5 means the widget is placed in the 50% of the window width and 50% of the window height.
relx=1.0 is the right boundary of the window, and
rely=1.0 is the bottom boundary of the window.