Tkinter如何组织或者说是堆叠组件呢?它提供了三种组件管理器,用予组织各组件:
- pack
- grid
- place
Pack()将搭建好组件,进行在Window或者 frame上进行展示。主要有以下 几个属性
- side
- expand
- fill
- ipadx,ipady
- padx,pady
- anchor
再回顾一下tkinter的坐标系:
左上角是(0,0),横向为x,纵向为y。
一段简单的组件堆叠代码:
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')
label1.pack()
label2.pack()
label3.pack()
root.mainloop()
执行结果:
1、side
可见,三个label在Y方向上,从上往下依次摆放。这个堆叠的方向,是由side来控制的。side的取值:
- top(默认值)
- bottom
- left
- right
这四个取值,可以分别用预定义常量来替换tk.TOP、tk.BOTTOM、tk.LEFT、tk.RIGHT
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')
label1.pack(side=tk.BOTTOM)#label1.pack(side='bottom')
label2.pack(side=tk.BOTTOM)#label1.pack(side='bottom')
label3.pack(side=tk.BOTTOM)#label1.pack(side='bottom')
root.mainloop()
执行结果:
类似的,可以设置成 tk.LEFT 、 tk.RIGHT。
widget space
tkinter中有两个空间跨度,一个是组件所占的空间,另一个是组件可以拥有的空间。例如 , 一个组件根据其内容的大小占有的一定的空间,然后,实际上,这个组件可以视windows或者 frame,实际占用更多的空间。
expand
通过expand=True,可以让组件实际占用的空间更大,在横向或纵向上进行扩展,取决于堆叠的方向。如果组件是竖向堆叠的,则组件的height将扩大,如果是横向堆叠的,width将更多。
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')
label1.pack(side=tk.TOP, expand=True)
label2.pack(side=tk.TOP, expand=False)
label3.pack(side=tk.TOP, expand=False)
root.mainloop()
label1将在纵向上占据更多空间。
横向扩展:
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')
label1.pack(side=tk.LEFT, expand=True)
label2.pack(side=tk.LEFT, expand=False)
label3.pack(side=tk.LEFT, expand=False)
root.mainloop()
运行结果:
均分空间的例子,将所有组件的expand设置为True.
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Demo',bg='blue', fg='white')
label1.pack(side=tk.LEFT, expand=True)
label2.pack(side=tk.LEFT, expand=True)
label3.pack(side=tk.LEFT, expand=True)
root.mainloop()
fill
组件可以占据它可以填满的区域,fill可以设定如下值:
- none:依据实际大小填充空间
- x:水平方向上填满空间
- y:垂直方向上填满空间
- both:水平和竖直方向上填满空间
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Tkinter',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack Layout',bg='green', fg='white')
label3 = tk.Label(master=root, text='Fill',bg='blue', fg='white')
label4 = tk.Label(master=root, text='Demo',bg='purple', fg='white')
label1.pack(side=tk.TOP, expand=True, fill=tk.X)
label2.pack(side=tk.TOP, expand=True, fill=tk.Y)
label3.pack(side=tk.TOP, expand=True, fill=tk.NONE)
label4.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
root.mainloop()
执行结果:
ipadx ipady
分别在组件内部的左右或者上下进行pad填充
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Pack',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack',bg='green', fg='white')
label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white')
label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white')
label1.pack(side=tk.LEFT)
label2.pack(side=tk.LEFT, ipadx=40)
label3.pack(side=tk.LEFT, ipady=40)
label4.pack(side=tk.LEFT, ipadx=80, ipady=80)
root.mainloop()
执行结果:
padx pady
组件外部的左右、上下进行pad填充。
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Pack',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack',bg='green', fg='white')
label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white')
label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white')
label1.pack(side=tk.TOP, fill=tk.X, pady=10)
label2.pack(side=tk.TOP, fill=tk.X, pady=20)
label3.pack(side=tk.TOP, fill=tk.X ,pady=40)
label4.pack(side=tk.TOP, fill=tk.X, pady=60)
root.mainloop()
运行结果:
如下,是padx
import tkinter as tk
root = tk.Tk()
root.title('Tkinter Pack Layout')
root.geometry('600x400')
label1 = tk.Label(master=root, text='Pack',bg='red',fg='white')
label2 = tk.Label(master=root,text='Pack',bg='green', fg='white')
label3 = tk.Label(master=root, text='Pack',bg='blue', fg='white')
label4 = tk.Label(master=root, text='Pack',bg='purple', fg='white')
label1.pack(side=tk.LEFT, fill=tk.X, padx=10)
label2.pack(side=tk.LEFT, fill=tk.X, padx=20)
label3.pack(side=tk.LEFT, fill=tk.X ,padx=40)
label4.pack(side=tk.LEFT, fill=tk.X, padx=60)
root.mainloop()
运行结果:
anchor
设定组件在分配的空间上贴靠的位置,可以由以下设置:
- n
- s
- e
- w
- nw
- ne
- se
- sw
- center
可能参照下图:
import tkinter as tk
root = tk.Tk()
root.title('Pack Demo')
root.geometry("350x200")
# box 1
box1 = tk.Label(root, text="Box 1", bg="green", fg="white")
box1.pack(ipadx=20, ipady=20, anchor=tk.E, expand=True)
# box 2
box2 = tk.Label(root, text="Box 2", bg="red", fg="white")
box2.pack(ipadx=20, ipady=20, anchor=tk.W, expand=True)
root.mainloop()
通过pack,完成一个登录框。
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title('Login')
root.geometry("350x220")
fields = {}
fields['username_label'] = ttk.Label(text='Username:')
fields['username'] = ttk.Entry()
fields['password_label'] = ttk.Label(text='Password:')
fields['password'] = ttk.Entry(show="*")
for field in fields.values():
field.pack(anchor=tk.W, padx=10, pady=5, fill=tk.X)
ttk.Button(text='Login').pack(anchor=tk.W, padx=10, pady=5)
root.mainloop()