布局管理器
一个GUI 应用程序必然有大量的组件,这些组件如何排布?这时候,就需要使用tkinter提供的布局管理器帮助我们组织、管理在父组件中子组件的布局方式。tkinter 提供了三种管理器:pack、grid、place
。
grid
布局管理器
grid
表格布局,采用表格结构组织组件。子组件的位置由行和列的单元格来确定,并且可以跨行和跨列,从而实现复杂的布局。
grid()方法提供的选项
选项项 | 说明 | 取值范围 |
---|---|---|
column | 单元格的列号 | 从0 开始的正整数 |
columnspan | 跨列,跨越的列数 | 正整数 |
row | 单元格的行号 | 从0 开始的正整数 |
rowspan | 跨行,跨越的行数 | 正整数 |
ipadx, ipady | 设置子组件之间的间隔,x 方向或者y 方向,默认单位为像素 | 非负浮点数,默认0.0 |
padx, pady | 与之并列的组件之间的间隔,x 方向或者y 方向,默认单位是像素 | 非负浮点数,默认0.0 |
sticky | 组件紧贴所在单元格的某一角,对应于东南西北中以及4 个角 | “n”, “s”, “w”, “e”,“nw”, “sw”, “se”,“ne”, “center”(默认) |
示例 grid 布局用法-登录界面设计
from tkinter import *
from tkinter import messagebox
import random
class Application(Frame):
def __init__(self, master=None):
super().__init__(master) # super()代表的是父类的定义,而不是父类对象
self.master = master
self.pack()
self.createWidget()
def createWidget(self):
"""通过grid 布局实现登录界面"""
self.label01 = Label(self,text="用户名")
self.label01.grid(row=0,column=0)
self.entry01 = Entry(self)
self.entry01.grid(row=0,column=1)
Label(self,text="用户名为手机号").grid(row=0,column=2)
Label(self, text="密码").grid(row=1, column=0)
Entry(self, show="*").grid(row=1, column=1)
Button(self, text="登录").grid(row=2, column=1, sticky=EW)
Button(self, text="取消").grid(row=2, column=2, sticky=E)
if __name__ == '__main__':
root = Tk()
root.geometry("400x90+200+300")
app = Application(master=root)
root.mainloop()
示例 通过grid 布局-实现计算器软件界面
"""计算器软件界面的设计"""
from tkinter import *
from tkinter import messagebox
import random
class Application(Frame):
def __init__(self, master=None):
super().__init__(master) # super()代表的是父类的定义,而不是父类 对象
self.master = master
self.pack()
self.createWidget()
def createWidget(self):
"""通过grid 布局实现计算器的界面"""
btnText = (("MC", "M+", "M-", "MR"),
("C", "±", "/", " "),
(7, 8, 9, "-"),
(4, 5, 6, "+"),
(1, 2, 3, "="),
(0, "."))
Entry(self).grid(row=0, column=0, columnspan=4, pady=10)
for rindex, r in enumerate(btnText):
for cindex, c in enumerate(r):
if c == "=":
Button(self, text=c, width=2).grid(row=rindex + 1, column=cindex, rowspan=2, sticky=NSEW)
elif c == 0:
Button(self, text=c, width=2).grid(row=rindex + 1, column=cindex, columnspan=2, sticky=NSEW)
elif c == ".":
Button(self, text=c, width=2) \
.grid(row=rindex + 1, column=cindex + 1, sticky=NSEW)
else:
Button(self, text=c, width=2) \
.grid(row=rindex + 1, column=cindex, sticky=NSEW)
if __name__ == '__main__':
root = Tk()
root.geometry("200x200+200+300")
app = Application(master=root)
root.mainloop()
pack
布局管理器
pack
按照组件的创建顺序将子组件添加到父组件中,按照垂直或者水平的方向自然排布。如果不指定任何选项,默认在父组件中自顶向下垂直添加组件。pack
是代码量最少,最简单的一种,可以用于快速生成界面。
pack()方法提供的选项
名称 | 描述 | 取值范围 |
---|---|---|
expand | 当值为“yes”时,side 选项无效。组件显示在父配件中心位置;若fill 选项为”both”,则填充父组件的剩余空间 | “yes”, 自然数,”no”, 0(默认值”no”或0) |
fill | 填充x(y)方向上的空间,当属性side=”top”或”bottom”时,填充x 方向;当属性side=”left”或”right”时,填充”y”方向;当expand 选项为”yes”时,填充父组件的剩余空间 | “x”, “y”, “both”,“none”(默认值为none) |
ipadx,ipady | 设置子组件之间的间隔,x 方向或者y 方向,默认单位为像素 | 非负浮点数,默认0.0 |
padx,pady | 与之并列的组件之间的间隔,x 方向或者y 方向,默认单位是像素 | 非负浮点数,默认0.0 |
side | 定义停靠在父组件的哪一边上 | “ top ” , “ bottom ” ,“left”, “right”(默认为”top”) |
before | 将本组件于所选组建对象之前pack,类似于先创建本组件再创建选定组件 | 已经pack 后的组件对象 |
after | 将本组件于所选组建对象之后pack,类似于先创建选定组件再本组件 | 已经pack 后的组件对象 |
in_ | 将本组件作为所选组建对象的子组件,类似于指定本组件的master 为选定组件 | 已经pack 后的组件对象 |
anchor | 对齐方式,左对齐”w”,右对齐”e”,顶对齐”n”,底对齐”s” | “n”, “s”, “w”, “e”,“nw”, “sw”, “se”,“ne”, “center”(默认) |
建议 :如上列出了pack 布局所有的属性,但是不需要挨个熟悉,了解基本的即可。pack 适用于简单的垂直或水平排布,如果需要复杂的布局可以使用grid 或place。
示例 pack 布局用法,制作钢琴按键布局
#coding=utf-8
#测试pack 布局管理
from tkinter import *
root = Tk();root.geometry("700x220")
#Frame 是一个矩形区域,就是用来防止其他子组件
f1 = Frame(root)
f1.pack()
f2 = Frame(root);f2.pack()
btnText = ("流行风","中国风","日本风","重金属","轻音乐")
for txt in btnText:
Button(f1,text=txt).pack(side="left",padx="10")
for i in range(1,20):
Button(f2,width=5,height=10,bg="black" if i%2==0 else
"white").pack(side="left")
root.mainloop()
place
布局管理器
place
布局管理器可以通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景。
place()方法的选项
选项 | 说明 | 取值范围 |
---|---|---|
x,y | 组件左上角的绝对坐标(相对于窗口) | 非负整数x 和y 选项用于设置偏移( 像素) , 如果同时设置relx(rely) 和x(y),那么place 将优先计算relx 和rely,然后再实现x 和y 指定的偏移值 |
relx,rely | 组件左上角的坐标(相对于父容器) | relx 是相对父组件的位置。0 是最左边,0.5 是正中间,1是最右边;rely 是相对父组件的位置。0 是最上边,0.5 是正中间,1是最下边; |
width,height | 组件的宽度和高度 | 非负整数 |
relwidth,relheight | 组件的宽度和高度(相对于父容器) | 与relx、rely 取值类似,但是相对于父组件的尺寸 |
anchor | 对齐方式,左对齐”w”,右对齐”e”,顶对齐”n”,底对齐”s” | “n”, “s”, “w”, “e”, “nw”, “sw”, “se”,“ne”, “center”(默认) |
示例 place 布局管理-基本用法测试
#coding=utf-8
from tkinter import *
root = Tk();root.geometry("500x300")
root.title("布局管理place");root["bg"]="white"
f1 = Frame(root,width=200,height=200,bg="green")
f1.place(x=30,y=30)
Button(root,text="ccc").place(relx=0.5,rely=0,
x=100,y=200,relwidth=0.2,relheight=0.2)
Button(f1,text="天空程序员").place(relx=0.6,rely=0.7)
Button(f1,text="beijingnihao").place(relx=0.2,rely=0.2)
root.mainloop()
示例 place 布局管理-扑克牌游戏demo
from tkinter import *
class Application(Frame):
def __init__(self, master=None):
super().__init__(master) # super()代表的是父类的定义,而不是父类对象
self.master = master
self.pack()
self.createWidget()
def createWidget(self):
"""通过place 布局管理器实现扑克牌位置控制"""
# self.photo = PhotoImage(file="imgs/puke/puke1.gif")
# self.puke1 = Label(self.master,image=self.photo)
# self.puke1.place(x=10,y=50)
self.photos = [PhotoImage(file=r"F:\python_l\pythonProject1\puke\puke"+str(i+1)+".gif") for i in range(10)]
self.pukes = [Label(self.master,image=self.photos[i]) for i in range(10)]
for i in range(10):
self.pukes[i].place(x=10+i*40,y=50)
# 为所有的Label 增加事件处理
self.pukes[0].bind_class("Label","<Button-1>",self.chupai)
def chupai(self,event):
print(event.widget.winfo_geometry())
print(event.widget.winfo_y())
if event.widget.winfo_y() == 50:
event.widget.place(y=30)
else:
event.widget.place(y=50)
if __name__ == '__main__':
root = Tk()
root.geometry("600x270+200+300")
app = Application(master=root)
root.mainloop()