做一个应用程序,肯定需要更多的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.py

from 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()

python中tkinter的pack方法 tkinter pack()_tkinter


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

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

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

#coding:UTF-8
#ch2.py --ch1.py 2.0

from 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()

python中tkinter的pack方法 tkinter pack()_tkinter_02


再改成LEFT

#coding:UTF-8
#ch3.py -- ch2.py->side->LEFT

from 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()

python中tkinter的pack方法 tkinter pack()_widget_03


混合使用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()

python中tkinter的pack方法 tkinter pack()_tkinter_04

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等会讲,运行结果

python中tkinter的pack方法 tkinter pack()_ide_05


3️⃣ipadx / ipady参数

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

python中tkinter的pack方法 tkinter pack()_python_06


4️⃣anchor参数

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

python中tkinter的pack方法 tkinter pack()_gui_07

实例:

#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更好一些吧

python中tkinter的pack方法 tkinter pack()_tkinter_08


那么再加上一个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()

python中tkinter的pack方法 tkinter pack()_python_09


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()

python中tkinter的pack方法 tkinter pack()_ide_10


如果所分配容器空间已经满了,则使用fill没有任何作用,将wxPython那个标签设置为.pack(fill=Y)不会有任何效果。

6️⃣expand参数

expand参数可设定Widget控件是否填满额外的父容器空间,默认是False(或0),表示不填满,如果是True(或是1)则填满。这很重要!

python中tkinter的pack方法 tkinter pack()_python_11

不管怎么设置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()

python中tkinter的pack方法 tkinter pack()_gui_12

#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()

python中tkinter的pack方法 tkinter pack()_tkinter_13


7️⃣pack参数

  • forget()——隐藏Widget控件,可以用pack(option, ...)复原
  • info()——传回pack选项的对应值
  • size()——传回Widget控件的大小