9.5 布局管理器

Frame组件
Frame是一种容器组件,通常用来做宏观布局,然后里面可以放更小的组件。
如下所示:
import tkinter as tk  
  
root = tk.Tk()
frame = tk.Frame(root)  
frame.pack()  
  
label = tk.Label(frame, text="这是一个标签")  
label.pack()  
  
button = tk.Button(frame, text="这是一个按钮")  
button.pack()  
  
label = tk.Label(frame, text="这是另一个标签")  
label.pack()  
  
button = tk.Button(frame, text="这是另一个按钮")  
button.pack()  
  
root.mainloop()
这里包含了两个标签,两个按钮,都放置在一个Frame框架里。下一节,关于布局可以看到frame更多的应用。

布局是指组件的排列方式,主要有三种:
pack布局方式
pack()是 Tkinter 的布局管理方法之一,其作用是将组件放在它所在容器中的一个 Frame 中,Frame 按照 Tkinter 布局规则摆放。
具体来说,
pack(side=LEFT/RIGHT/TOP/BOTTOM)# 可以使得组件按照指定的方向排列
pack(fill=BOTH)# 使得组件充满整个 Frame
pack(expand=YES)# 则使得组件可以在所在容器中自由伸缩
以下是一个简单的例子,以展示pack()的具体用法:
import tkinter as tk
root = tk.Tk()
frame1 = tk.Frame(root, bg="red", width=200, height=200)
frame2 = tk.Frame(root, bg="blue", width=200, height=200)
frame3 = tk.Frame(root, bg="green", width=200, height=200)
frame1.pack(side="top", fill="both", expand=True)
frame2.pack(side="left", fill="both", expand=True)
frame3.pack(side="right", fill="both", expand=True)
root.mainloop()
在这个例子中,我们创建了三个不同颜色的 Frame,并使用 pack()将它们按照指定的方式放置在主窗口中。
frame1在容器的顶部,通过 `fill="both", expand=True` 让它充满整个容器;
frame2` 在左侧,`frame3` 在右侧,同样充满整个容器。
运行代码,我们可以看到三个 Frame 成功地按照我们的要求排列在主窗口中,并占据了相应的空间。最终效果如图:
place布局
place()是 Tkinter 提供的一种用于布局组件的方法,其作用是直接指定组件在其容器中的精确位置,以及组件的宽度和高度。 place()的语法格式为(假设w是一个组件):
w.place(
    x = 100,     # 组件左上角的 x 坐标
    y = 150,     # 组件左上角的 y 坐标
    width = 50, # 组件的宽度
    height = 20 # 组件的高度
)
下面是一个place的例子:
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg="lightblue", width=200, height=200)
frame.place(x=100, y=100)
root.mainloop()
在这个例子中,我们创建了一个背景为浅蓝色的 Frame,并使用 place()指定它在主窗口中左上角的位置为 (100, 100)。运行代码,我们可以看到 Frame 成功地被放置在了指定的位置上。需要注意的是,使用 place()`布局时需要手动计算组件的具体位置,因此需要耗费一定的时间和精力。最终效果如图:

grid布局
就是表格布局。
grid()可以将组件放在网格中。与 place()和pack()不同,grid()布局通常比较灵活,可以根据实际需要指定每个单元格的大小、位置、行列跨度等信息。 以下是grid布局函数的参数说明
widget.grid(
    row = ...,              # 组件所在的行数
    column = ...,           # 组件所在的列数
    columnspan = ...,       # 组件的列跨度
    rowspan = ...,          # 组件的行跨度
    padx = ...,             # 组件的水平边距
    pady = ...,             # 组件的垂直边距
    ipadx = ...,            # 组件的内部水平边距
    ipady = ...             # 组件的内部垂直边距
)
其中,row和column分别表示组件所在的行数和列数;
columnspan和rowspan分别表示组件的列跨度和行跨度;
padx和pady分别表示组件的外部水平和垂直边距,即组件与其他组件之间的间距;
ipadx 和 ipady表示组件的内部水平和垂直边距,即组件内容和组件边界之间的间距。
以下是一个布局的例子:
import tkinter as tk
root = tk.Tk()
label1 = tk.Label(root, text="Hello, World!")
label2 = tk.Label(root, text="This is Tkinter!")
label3 = tk.Label(root, text="Grid Layout")
label1.grid(row=0, column=0, padx=10, pady=10)
label2.grid(row=1, column=0, padx=10, pady=10)
label3.grid(row=0, column=1, rowspan=2, padx=10, pady=10)
root.mainloop()
在这个例子中,我们将三个 Label 组件放在 Tkinter 中的网格中。其中,label1放在第一行第一列,label2放在第二行第一列,label3放在第一行第二列,占据两行一列。我们还为每个组件设置了外部和内部边距。运行代码,我们可以看到三个 Label 成功地被放置在指定的位置上。 需要注意的是,使用 grid()进行布局时,需要自行指定每个组件所在的行数和列数,且每个行、列的大小需要根据实际情况适当调整。但相对于 place() 布局,grid()处理起来也更加方便、灵活。最终效果如图: