0️⃣前言
此文章代码都在Github:3-窗口控件配置管理员/pack方法别忘了⭐️呀


做一个应用程序,肯定需要更多的widget控件,所以这时候就牵扯到了如何将这些widget控件配置到 容器窗口 内。在设计GUI程序时,可以使用三种方法包装和定为各组件在 容器窗口 内的位置,这三个方法又称窗口控件配置管理员(Widget Layout Manager),通常叫做布局方法

一共有三种布局方法:pack、grid和place,最常用的是pack方法,本章介绍pack方法

窗口控件配置管理员

  • 前言
  • side参数
  • padx/pady参数
  • ipadx/ipady参数
  • anchor参数
  • fill参数
  • expand参数
  • pack参数

pack方法的语法格式如下

***.pack(options, ...)

options参数可以是如下属性:

  • side
  • fill
  • padx/pady
  • ipadx/ipady
  • anchor

下面将详细说明
1️⃣side参数
可以垂直或水平配置控件,可以设置控件的排列顺序

#coding:UTF-8
#ch1.pyfrom tkinter import *root = Tk()
root.title("普通设置控件")Label(root, text="Tkinter", bg="lightyellow").pack()
#第一个标签
#这些标签不需要保存在变量中,设置好直接布局
Label(root, text="wxPython", bg="lightgreen").pack()Label(root, text="PyQt", bg="lightblue").pack()root.mainloop()


如果窗口中有多个控件,pack会自动让控件从上往下排列显示,这是默认设置。也可以使用side参数改变排列方式,此参数取值如下

  • TOP:默认值,由上往下排列
  • BOTTOM由下往上排列
  • LEFT从左往右排列
  • RIGHT从右往左排列

重新改造,使用side,并让标签的宽度都为15

#coding:UTF-8
#ch2.py --ch1.py 2.0from tkinter import *root = Tk()
root.title("普通设置控件")Label(root, text="Tkinter", bg="lightyellow", width=15).pack(side=BOTTOM)
#第一个标签
#这些标签不需要保存在变量中,设置好直接布局
Label(root, text="wxPython", bg="lightgreen", width=15).pack(side=BOTTOM)Label(root, text="PyQt", bg="lightblue", width=15).pack(side=BOTTOM)root.mainloop()


再改成LEFT

#coding:UTF-8
#ch3.py -- ch2.py->side->LEFTfrom tkinter import *root = Tk()
root.title("普通设置控件")Label(root, text="Tkinter", bg="lightyellow", width=15).pack(side=LEFT)
#第一个标签
#这些标签不需要保存在变量中,设置好直接布局
Label(root, text="wxPython", bg="lightgreen", width=15).pack(side=LEFT)Label(root, text="PyQt", bg="lightblue", width=15).pack(side=LEFT)root.mainloop()


混合使用side

#coding:UTF-8
#ch4.py -- ch3.py->side->混合使用from tkinter import *root = Tk()
root.title("普通设置控件")Label(root, text="Tkinter", bg="lightyellow", width=15).pack()
#第一个标签
#这些标签不需要保存在变量中,设置好直接布局
Label(root, text="wxPython", bg="lightgreen", width=15).pack(side=RIGHT)Label(root, text="PyQt", bg="lightblue", width=15).pack(side=LEFT)root.mainloop()

2️⃣padx / pady参数
可以使用padx/pady参数设定控件边界与容器(可以想成窗口边界)的距离或是控件边界间的距离。在默认环境下窗口控件间的距离是 1 像素,如果希望有适度间距,可以设置padx/pady,代表水平间距/垂直间距


实例:

#coding:UTF-8
from tkinter import *root = Tk()
root.title("relief")Label(root, text="flat", relief="flat").pack(side=LEFT, pady=5, padx=4, ipadx=10, ipady=10)
Label(root, text="groove", relief="groove").pack(side=LEFT, pady=5, padx=4, ipadx=10, ipady=10)
Label(root, text="raised", relief="raised").pack(side=LEFT, pady=5, padx=4, ipadx=10, ipady=10)
Label(root, text="ridge", relief="ridge").pack(side=LEFT, pady=5, padx=4, ipadx=10, ipady=10)
Label(root, text="solid", relief="solid").pack(side=LEFT, pady=5, padx=4, ipadx=10, ipady=10)
Label(root, text="sunken", relief="sunken").pack(side=LEFT, pady=5, padx=4, ipadx=10, ipady=10)root.mainloop()

用relief参数实现各种标签的边框,ipadx和ipady等会讲,运行结果

3️⃣ipadx / ipady参数
ipadx/ipady是调整内部距离的,padx/pady是调整外部距离的,还是刚才的程序运行结果,再次分析

4️⃣anchor参数
可以设定Widget控件在窗口中的位置,参数如下


实例:

#coding: UTF-8
#ch7.py anchor
from tkinter import *
root = Tk()
root.title("ch7.py")
root.geometry("300x180")
okbtn = Button(root, text="OK",font="Times 20 bold",fg="white", bg="blue")
okbtn.pack(anchor=S, side=RIGHT,padx=10, pady=10)
root.mainloop()

原本书中写的是Label的,因为这个是鉴于刚学了Label其他的都不知道的同学看的,我觉得既然是OK,Button更好一些吧

那么再加上一个NO键是不是更好?

#coding: UTF-8
#ch8.py anchor + NO BTN
from tkinter import *
root = Tk()
root.title("ch7.py")
root.geometry("300x180")
okbtn = Button(root, text="OK",font="Times 20 bold",fg="white", bg="blue")
okbtn.pack(anchor=S, side=RIGHT,padx=10, pady=10)
nobtn = Button(root, text = "NO",font="Times 20 bold",fg="white", bg="red")
nobtn.pack(anchor=S, side=RIGHT,pady=10)
root.mainloop()


5️⃣fill参数
此参数是告诉pack管理程序,设置控件填满所分配容器区间的方式,如果是fill=X表示控件可以填满所分配空间X轴不留白,反之亦然,如果是fill=BOTH表示控件可以填满所分配空间的X轴和Y轴。fill的默认值是None,表示保持原始大小。

实例:(改编第一个ch1.py)

#coding:UTF-8
#ch9.py fill
from tkinter import *root = Tk()
root.title("普通设置控件")Label(root, text="Tkinter", bg="lightyellow").pack(fill=X)
#第一个标签
#这些标签不需要保存在变量中,设置好直接布局
Label(root, text="wxPython", bg="lightgreen").pack()Label(root, text="PyQt", bg="lightblue").pack(fill=X)root.mainloop()


如果所分配容器空间已经满了,则使用fill没有任何作用,将wxPython那个标签设置为.pack(fill=Y)不会有任何效果。
6️⃣expand参数
expand参数可设定Widget控件是否填满额外的父容器空间,默认是False(或0),表示不填满,如果是True(或是1)则填满。这很重要!

不管怎么设置fill参数,其结果都没有填满整个窗口,于是expand隆重出场!

#coding:UTF-8
#ch9.py fill
from tkinter import *root = Tk()
root.title("expand")Label(root, text="Tkinter", bg="lightyellow").pack(side=LEFT, fill=Y)
#第一个标签
#这些标签不需要保存在变量中,设置好直接布局
Label(root, text="wxPython", bg="lightgreen").pack(fill=X)Label(root, text="PyQt", bg="lightblue").pack(fill=BOTH, expand=True) #设置可以变化root.mainloop()

#coding:UTF-8
#ch9.py fill
from tkinter import *root = Tk()
root.title("expand")Label(root, text="Tkinter", bg="lightyellow").pack(side=LEFT, fill=Y)
#第一个标签
#这些标签不需要保存在变量中,设置好直接布局
Label(root, text="wxPython", bg="lightgreen").pack(fill=BOTH, expand=True)Label(root, text="PyQt", bg="lightblue").pack(fill=BOTH, expand=True) #设置可以变化root.mainloop()


7️⃣pack参数