编写程序的GUI界面,我们需要把各个组件,以适当大小,定位到界面的某个位置。tkinter以提供3种界面组件布局管理的方法,分别是:pack,grid,place 这篇文章先来讲解pack 方法。
pack
pack()方法的参数有:side,fill,padx/pady,ipadx/ipady,anchor,expand
- side:决定组件停靠的方向。有left, right, top, bottom四个选项
- fill:决定组件是否填充,以及填充的方向,有:x横向填充, y纵向填充, both双向填充, none不填充四个选项。
- padx/pady: 组件外,组件跟邻近组件或窗体边界的距离(外边距)
- ipadx/ipady: 组件内,组件文本跟组件边界之间的距离(内边距)
- anchor: 决定组件停靠的位置
- expand:bool,决定组件的“势力范围”是否扩大到“扩展范围”
import tkinter as tk
class Main(tk.Tk):
def __init__(self) -> None:
super().__init__()
self.set_pack()
self.mainloop() #主循环一定要有,要不然不会显示。
def set_pack(self):
self.lb1 = tk.Label(text='第一个标签',background='red')
self.lb2 = tk.Label(text='第二个标签',background='yellow')
self.lb3 = tk.Label(text='第三个标签',background='blue')
self.lb1.pack(side='bottom')
self.lb2.pack(side='bottom')
self.lb3.pack(side='bottom')
if __name__ == "__main__":
main = Main()
bottom换成left试试。
import tkinter as tk
class Main(tk.Tk):
def __init__(self) -> None:
super().__init__()
self.geometry('300x400+500+500')
self.set_pack()
self.mainloop() #主循环一定要有,要不然不会显示。
def set_pack(self):
self.lb1 = tk.Label(text='第一个标签',background='red')
self.lb2 = tk.Label(text='第二个标签',background='yellow')
self.lb3 = tk.Label(text='第三个标签',background='blue')
self.lb1.pack(side='left',expand=False,fill='x')
self.lb2.pack(side='left',expand=False,fill='y')
self.lb3.pack(side='left',expand=True,fill="both")
if __name__ == "__main__":
main = Main()
其实我们可以把side的实参当成一个大磁铁,它会根据pack的顺序把控件一个一个“吸附”到那个位置。
多讲一下expand,当expand=False:
- 当side='top’和side=‘bottom’,只能横向填充,即fill=‘x’
- 当side='left’和side=‘right’,只能纵向填充,即fill=‘y’
当expand=True:
当 expand=True 时,填充时,可以横向填充,也可以纵向填充,也要横向纵向同时填充,即 fill=’both’
我们看上图,第一个标签,灰色部分是它的势力范围,但它只能纵向填充,所以填充失败。第二个标签填充成功,整个势力范围成为黄色,第三个标签宽度超过了前两个标签,因为它把“剩下的空间”填满了,超出势力范围的部分就是它的扩展范围。
单个组件或少量组件直接用pack方法来定位还简单,但要是很多的组件在窗体来用pack方法来定位就复杂了,所以编程时,用pack()来定位时,一般是结合frame组件来定位,这可以让界面编写代码简单化。
import tkinter as tk
class Main(tk.Tk):
def __init__(self) -> None:
super().__init__()
self.geometry('300x400+500+500')
self.set_pack()
self.mainloop() #主循环一定要有,要不然不会显示。
def set_pack(self):
self.frm = tk.Frame(background='green',padx=5,pady=2,relief='ridge')
self.lb1 = tk.Label(master=self.frm,text='第一个标签',background='red') #master是将控件放到哪个背景板上,默认是在self上,不在self上的话,这里我们把它放到self.frm上。
self.lb2 = tk.Label(master=self.frm,text='第二个标签',background='yellow')
self.lb3 = tk.Label(text='第三个标签',background='blue')
self.frm.pack(expand=True)
self.lb1.pack(side='bottom')
self.lb2.pack(side='bottom')
self.lb3.pack(side='bottom')
if __name__ == "__main__":
main = Main()
这是效果。
我们再来看一下grid,这个是最常用的。
主要参数:
- row:组件定位表格的行
- column:组件定位表格的列
- ipadx/ipady:填充表格框,让表格框在X/Y方向上变胖
- padx/pady:决定组件跟邻近表格线或窗体边界的距离
- rowspan:组件跨多少列表格框,默认1个组件占用1行1列
- columnspan:组件跨多少行表格框,默认1个组件占用1行1列
- sticky:当表格框大小组件的大小,组件默认居中显示,那这个表格框周围的空白部分,如何分配,这就由sticky来决定。具体规定如下:
默认组件在表格框中是居中对齐显示,但通过sticky可以设定N/S/W/E即上、下、左、右对齐,NSWE也可以组件使用:
- sticky=N+S 拉高组件,让组件上下填充到表格框的顶端和底端。
- sticky=N+S+E 拉高组件,让组件上下填充到表格框的顶端和底端,同时,,让组件靠右对齐。
- sticky=N+W+E 拉高拉宽组件,让组件填充满一个表格框。
表格中每一行的高度,以这一行最高组件为基准。
表格中每一列的宽度,以这一列最宽组件为基准。
表格行、列的计数,都是从0开始,如第一行第一列用:row=0,column=0来表示。
import tkinter as tk
class Main(tk.Tk):
def __init__(self) -> None:
super().__init__()
self.geometry('300x400+500+500')
self.set_grid()
self.mainloop() #主循环一定要有,要不然不会显示。
def set_grid(self):
self.lb1=tk.Label(text='第一个',background='red').grid(row=0,column=0)
self.lb2=tk.Label(text='第二个',background='red').grid(row=0,column=1)
self.lb2=tk.Label(text='第三个',background='red').grid(row=1,column=0,columnspan=2)
self.lb2=tk.Label(text='第三个',background='red').grid(row=1,column=2,ipadx=5,ipady=10)
self.lb2=tk.Label(text='第四个',background='red').grid(row=2,column=0)
self.lb2=tk.Label(text='第五个',background='red').grid(row=2,column=1)
self.lb2=tk.Label(text='第六个',background='red').grid(row=2,column=2)
self.lb2=tk.Label(text='第七个',background='red').grid(row=2,column=3)
if __name__ == "__main__":
main = Main()
place()布局定位方法,允许程序员准确指定组件的位置,大小。粗略一听,好像不错,但实际操作起来,根本不容易,我们除了屏幕左上角x=0,y=0可以准确知道,其他位置并不能很好地知道坐标。至于组件大小,以像素为单位,同样不太好掌握。所以这种方法了解即可。
- place(参数1,参数2,……)
参数:x,y 组件左上角在界面上的横向和纵向坐标,单位是像素。(再提醒一下,默认情况下,这个x,y坐标是指组件的左上角在界面上的位置)
- 参数:anchor锚点
这个参数决定组件以自身的那个一点去跟坐标相重合。默认情况下,是以组件的左上角去跟坐标相重合,即anchor=NW,所有选项:anchor=NW/N/NE/W/CENTER/E/SW/S/SE ,如果我们希望按钮的正中间点跟窗体的正中心重合,只要加参数 anchor=’center’ ,那么组件锚点,即按钮的正中心就会去跟坐标重合。
- 参数:relx/rely
这也是一个坐标值 ,但是一个相对坐标,是相对父组件的坐标,取值范围为0-1
窗体界面左上角坐标:relx=0,rely=0
窗体界面右上角坐标:relx=1,rely=1
窗体界面正中间坐标:relx=0.5,rely=0.5
窗体界面左下角坐标:relx=0,rely=1
窗体界面右下角坐标:relx=1,rely=1
- 参数:width/height 和 relwidth/relheight
width 指组件的宽度,单位是像素。
height 指组件的高度,单位是像素。
relwidth 指组件相对于父组件的宽度,取值范围为0-1
relheight指组件相对于父组件的高度,取值范围为0-1
具体代码大家自行测试,不再演示。