Widget Layout Manager 组件布局管理器,顾名思义是用来对组件进行布局管理的。好比一位画家在画布上进行各种元素创作时进行布局一样。
不禁好奇,为什么Tk不设计成每个组件自带布局管理功能。而要专门设计三个控件管理器?
最大的可能是为了设计的灵活性.控件只需要关心其功能;布局逻辑集中在布局管理器中,便于调整。
初识布局管理器
TK提供了三种布局管理器,pack、grid、place.
-
pack
"打包"的意思.指定方向(上下或左右)对组件进行布局.
-
grid
中文含义"网格"。名称体现了布局的方式:将父容器划分成 行(row)和列(column)组成的网格,然后根据网格坐标将控件放置在指定的位置上。
-
place
"放置、定位"之意。通过明确指定控件的 位置(坐标)和 大小(宽度、高度),将控件精确地放置在父容器的指定位置上。
同一父容器中,只能使用一种布局管理器.
布局管理器常用方法
1、pack
| 选项参数 | 作用 | 取值 |
| side | 控件间的排列方向 |
"top"(默认:由上往下排列、 "bottom":由下往上排列、 "left":由左往右排列、 "right":由右往左排列 |
| fill | 控件是否填充可用空间 | "none"(默认)、"x"、"y"、"both" |
| expand | (填充)是否应该扩展以填充任何父容器中未被占用的空间。 | True 或 False(默认) |
| anchor | (定位点) 控件在指定区域的对齐方式 | "center"(默认) |
| padx | 控件与周围控件或容器的水平间距 | 整数(像素单位) |
| pady | 控件与周围控件或容器的垂直间距 | 整数(像素单位) |
| ipadx | 控件内部内容(如按钮上文字、标签文本等)与控件水平侧的距离 | 整数(像素单位) |
| ipady | 控件内部内容(如按钮上文字、标签文本等)与控件垂直侧的距离 | 整数(像素单位) |
总结
-
排列方向: 使用side影响控件间的排列方向;使用anchor影响控件在父容器中的位置。
- 填充空间:使用fill和expand 对父容器空白处进行填充
- 间距: pad是padding(填充)缩写.i 是internal(内部的缩写).顾名思义:padx/pady 影响控件与周围控件的距离(填充);ipadx/ipady 影响控件内部内容与控件的距离(填充)。
2、grid
| 选项参数 | 作用 | 取值 |
| row | 控件所在的行位置 | ![]() |
| column | 控件所在的列位置 | |
| sticky | (粘附)控件在单元格内的对齐方式. |
功能类似anchor,但是只可以设定N/S/W/E,即上/下/左/右对齐. sticky=N+S |
| rowspan | 控件跨越的行数 | 整数,指定控件占用的行数。 |
| columnspan | 控件跨越的列数 | 整数,指定控件占用的列数。 |
| padx | 控件与周围控件或容器的水平间距 | 整数(像素单位) |
| pady | 控件与周围控件或容器的垂直间距 | 整数(像素单位) |
| ipadx | 控件内部内容(如按钮上文字、标签文本等)与控件水平侧的距离 | 整数(像素单位) |
| ipady | 控件内部内容(如按钮上文字、标签文本等)与控件垂直侧的距离 | 整数(像素单位) |
总结:
-
row和column来设置控件之间的位置。 sticky用于定义控件在单元格内的对齐方式。作用类似于单元格内对空余父容器进行填补。rowspan和columnspan用来让控件跨越多个行或列。padx、pady、ipadx、ipady用来控制控件的外边距和内边距,即控件和周围空间的距离。
3、place
| 选项参数 | 作用 | 取值 |
| x | 控件相对于父容器的水平偏移量 | 整数,表示控件的横坐标,单位为像素。 |
| y | 控件相对于父容器的垂直偏移量 | 整数,表示控件的纵坐标,单位为像素。 |
| width | 控件的宽度 | 整数,指定控件的宽度,单位为像素。 |
| height | 控件的高度 | 整数,指定控件的高度,单位为像素。 |
| anchor | 控件在指定位置的对齐方式 | "n"、"s"、"e"、"w"、"ne"、"se" 等,用于指定控件如何对齐于 (x, y) 点。 |
| relx | 控件的水平位置,相对于父容器的宽度的比例 | 浮动值,范围 0 到 1,表示控件的水平位置占父容器宽度的比例。 |
| rely | 控件的垂直位置,相对于父容器的高度的比例 | 浮动值,范围 0 到 1,表示控件的垂直位置占父容器高度的比例。 |
| relwidth | 控件的宽度,相对于父容器宽度的比例 | 浮动值,范围 0 到 1,表示控件宽度占父容器宽度的比例。 |
| relheight | 控件的高度,相对于父容器高度的比例 | 浮动值,范围 0 到 1,表示控件高度占父容器高度的比例。 |
总结:
place布局管理器通过绝对位置(x,y)或相对位置(relx,rely)来放置控件。anchor用于设置控件相对于指定位置的对齐方式。width和height设置控件的固定大小,relwidth和relheight则是设置控件大小的相对比例。
place 布局管理器特别适合需要精确控制控件位置的场景。
布局管理器代码实操
使用标签lable举例.
-
pack
from tkinter import *
# 创建窗口
root = Tk()
root.geometry("300x300+600+https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=200&pos_id=7jzYyvJO&pos_id=7jzYyvJO")
# 创建标签
lable1 = Label(root, text="红", bg="red")
lable2 = Label(root, text="黄", bg="yellow")
lable3 = Label(root, text="蓝", bg="blue")
lable4 = Label(root, text="绿", bg="green")
# ------ 布局 ----------------
# 默认布局:居中并从上往下排列
def pack_layout1():
root.title("pack 例子1 默认布局")
lable1.pack()
lable2.pack()
lable3.pack()
lable4.pack()
# 指定side布局
def pack_layout2():
root.title("pack 例子2 side")
lable1.pack(side=TOP)
lable2.pack(side=BOTTOM)
lable3.pack(side=LEFT)
lable4.pack(side=RIGHT)
# 指定fill布局,fill布局未起作用,因为top/bottom默认占据一行,left/right默认占据一列。
# 要想使其生效 需要使用expand(填充)
def pack_layout3():
root.title("pack 例子3 fill")
lable1.pack(side=TOP, fill=Y)
lable2.pack(side=BOTTOM, fill=Y)
lable3.pack(side=LEFT, fill=X)
lable4.pack(side=RIGHT, fill=X)
# expand布局
def pack_layout4():
root.title("pack 例子4 expand")
lable1.pack(side=TOP, fill=Y, expand=True)
lable2.pack(side=BOTTOM, fill=Y, expand=True)
lable3.pack(side=LEFT, fill=X, expand=True)
lable4.pack(side=RIGHT, fill=X, expand=True)
# anchor布局。
# 并不是在整个窗口进行布局.比如本例有4个标签组件,默认范围为4行(虽然pack中没有行的概念)。
# 而且控件没有出现在同一行
# 组件默认是按照**垂直方向(从上到下)**排列的,即side=TOP. anchor 只是控制组件在容器内的对齐位置
def pack_layout5():
root.title("pack 例子5 anchor")
lable1.pack(anchor=NW)
lable2.pack(anchor=NE)
lable3.pack(anchor=SW)
lable4.pack(anchor=SE)
# 根据例子5,布局出现在同一行
def pack_layout6():
root.title("pack 例子6 anchor")
lable1.pack(side=LEFT, anchor=NW)
lable2.pack(side=LEFT, anchor=NE)
lable3.pack(side=LEFT, anchor=SW)
lable4.pack(side=LEFT, anchor=SE)
# 间距布局
def pack_layout7():
root.title("pack 例子6 间隔")
lable1.pack(padx=20, pady=10, ipadx=10, ipady=5)
lable2.pack(padx=20, pady=10, ipadx=10, ipady=5)
lable3.pack(padx=20, pady=10, ipadx=10, ipady=5)
lable4.pack(padx=20, pady=10, ipadx=10, ipady=5)
# 使用布局
pack_layout7()
root.mainloop()
结果:







-
grid
from tkinter import *
# 创建窗口
root = Tk()
root.geometry("300x300+600+https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=200&pos_id=7jzYyvJO&pos_id=7jzYyvJO")
# 创建标签
lable1 = Label(root, text="红AAA", bg="red")
lable2 = Label(root, text="黄AAAAA", bg="yellow")
lable3 = Label(root, text="蓝AAAAAAA", bg="blue")
lable4 = Label(root, text="绿AAAAAAAAA", bg="green")
# ------ grid布局 ----------------
# 默认布局
def grid_layout1():
root.title("grid 例子1 默认布局")
lable1.grid()
lable2.grid()
lable3.grid()
lable4.grid()
# 指定行列.忽略某一行时,并不会空出来
def grid_layout2():
root.title("grid 例子2 指定行列")
lable1.grid(row=0, column=0)
lable2.grid(row=2, column=0)
lable3.grid(row=3, column=3)
lable4.grid(row=4, column=3)
# sticky布局,补充对齐
def grid_layout3():
root.title("grid 例子3 sticky")
lable1.grid(row=0, column=0, sticky=EW)
lable2.grid(row=2, column=0)
lable3.grid(row=3, column=3, sticky=EW)
lable4.grid(row=4, column=3)
# columnspan 布局
def grid_layout4():
root.title("grid 例子4 columnspan")
lable1.grid(row=0, column=0, sticky=EW)
lable2.grid(row=0, column=1, sticky=EW)
lable3.grid(row=1, column=0, columnspan=2, sticky=EW)
lable4.grid(row=2, column=0, sticky=EW)
# 使用布局
grid_layout1()
root.mainloop()
结果:




-
place
from tkinter import *
# 创建窗口
root = Tk()
root.geometry("300x300+600+200")
# 创建标签
lable1 = Label(root, text="红AAA", bg="red")
lable2 = Label(root, text="黄AAAAA", bg="yellow")
lable3 = Label(root, text="蓝AAAAAAA", bg="blue")
lable4 = Label(root, text="绿AAAAAAAAA", bg="green")
# ------ place布局 ----------------
# x,y布局,指定左上角坐标
def place_layout1():
root.title("place 例子1 ")
lable1.place(x=1, y=1)
lable2.place(x=100, y=200)
lable3.place(x=150, y=150)
lable4.place(x=200, y=100)
# 指定宽度、高度布局
def place_layout2():
root.title("place 例子2 ")
lable1.place(x=1, y=1)
lable2.place(x=100, y=200, width=100, height=30)
lable3.place(x=100, y=150, width=100, height=30)
lable4.place(x=200, y=100, width=100, height=300)
# 相对位置布局
def place_layout3():
root.title("place 例子3 ")
lable1.place(relx=0.5, rely=0.5, relwidth=0.3, relheight=0.1)
# 使用布局
place_layout3()
root.mainloop()
place 布局太过于精确,还是pack与grid更加友好.
总结
| 布局管理器 | 难度 | 适用场景 | 优点 | 缺点 |
| pack | 简单 | 简单线性布局 | 快速布局,代码简洁 | 缺乏精确控制 |
| grid | 中等 | 表格布局或需对齐的界面 | 精确位置,适合复杂布局 | 代码较复杂,需提前规划 |
| place | 较高 | 自由、不规则或定制布局 | 精确控制,灵活性高 | 难以动态适配,开发较繁琐 |


942

被折叠的 条评论
为什么被折叠?



