✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:python图形化GUI编程tkinter精讲
景天的主页:景天科技苑
文章目录
tkinter布局管理器
一个 GUI 应用程序必然有大量的组件,这些组件如何排布?
这时候,就需要使用 tkinter提供的布局管理器帮助我们组织、管理在父组件中子组件的布局方式。
tkinter 提供了三种管理器:pack、grid、place。
1.grid 布局管理器
grid 表格布局,采用表格结构组织组件。子组件的位置由行和列的单元格来确定,并
且可以跨行和跨列,从而实现复杂的布局。
【示例】grid 布局用法-登录界面设计
"""测试Grid布局管理器的基本用法,使用面向对象的方式""" from tkinter import * from tkinter import messagebox 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,pady=10) self.entry01 = Entry(self) self.entry01.grid(row=0,column=1,pady=10) Label(self,text="用户名为手机号",foreground="gray").grid(row=0,column=2) Label(self, text="密码").grid(row=1, column=0,pady=10) self.entry02 = Entry(self, show="*") self.entry02.grid(row=1, column=1,pady=10) #EW表示组件在水平方向上拉满该栅格 Button(self, text="登录",command=self.mylogin).grid(row=2, column=1, sticky=EW) Button(self, text="取消", command=root.destroy).grid(row=2, column=2, sticky=E) def mylogin(self): username = self.entry01.get() pwd = self.entry02.get() print("去数据库比对用户名和密码!") print("用户名:"+username) print("密码:"+pwd) if username=="13333333333" and pwd=="123456": messagebox.showinfo("景天科技苑学习系统", "登录成功!欢迎开始学习!") else: messagebox.showinfo("景天科技苑学习系统","登录失败!用户名或密码错误!") if __name__ == '__main__': root = Tk() root.geometry("500x120+200+300") root.title("用户登录") app = Application(master=root) root.mainloop()
运行
当输入错误的用户名或密码
当输入正确的用户名和密码
【示例】基于grid布局的计算器软件的设计案例
根据实际简易计算器的按键分布,设计一个相仿的计算器界面,相应的功能暂不需要实现。
如上界面,实际可以设计成一个 7 行 4 列的表格布局,然后将相应的按钮放置进去即可。
"""计算器软件界面的设计""" 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","±","/","x"), (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: #0跨列 Button(self,text=c,width=2)\ .grid(row=rindex+1,column=cindex,columnspan=2,sticky=NSEW) elif c == ".": # 由于0跨列了,所以点的列要加1 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("230x230+200+300") root.title('科学计算器') app = Application(master=root) root.mainloop()
运行,显示计算器界面
【示例】带有计算功能的计算器
import tkinter as tk def calculate(event): """根据用户输入计算结果并显示""" try: result = eval(entry.get()) entry.delete(0, tk.END) entry.insert(tk.END, str(result)) except Exception as e: entry.delete(0, tk.END) entry.insert(tk.END, "Error") def button_click(number): """在输入框中添加点击的数字或符号""" current = entry.get() entry.delete(0, tk.END) entry.insert(tk.END, current + str(number)) # 初始化Tkinter窗口 root = tk.Tk() root.title("简易计算器") root.geometry("400x360+500+300") # 创建一个输入框用于显示和输入数字 entry = tk.Entry(root, width=40, borderwidth=6) entry.bind("<Return>", calculate) # 绑定回车键触发计算 entry.grid(row=0, column=0, columnspan=4, padx=10, pady=10) # 定义按钮 buttons = [ ('7', 1, 0), ('8', 1, 1), ('9', 1, 2), ('/', 1, 3), ('4', 2, 0), ('5', 2, 1), ('6', 2, 2), ('*', 2, 3), ('1', 3, 0), ('2', 3, 1), ('3', 3, 2), ('-', 3, 3), ('0', 4, 0), ('.', 4, 1), ('=', 4, 2), ('+', 4, 3) ] # 创建按钮并放置在界面上 for (text, row, col) in buttons: if text == "=": tk.Button(root, text=text, padx=35, pady=20, command=lambda: calculate(None)).grid(row=row, column=col) else: tk.Button(root, text=text, padx=35, pady=20, command=lambda t=text: button_click(t)).grid(row=row, column=col) # 运行Tkinter事件循环 root.mainloop()
运行
按下等号得到结果
2.pack 布局管理器
pack 按照组件的创建顺序将子组件添加到父组件中,按照垂直或者水平的方向自然排
布。如果不指定任何选项,默认在父组件中自顶向下垂直添加组件。
pack 是代码量最少,最简单的一种,可以用于快速生成界面。
pack()参数详解:
编写一个程序的界面,就是要把各个组件,以适当大小,定位到界面的某个位置。
tkinter以提供3种界面组件布局管理的方法,分别是:pack,grid,place 这篇文章先来讲解pack 方法。
pack() 方法的参数有:side, fill, padx/pady, ipadx/ipady, anchor, expand等。
【老鸟建议】如上列出了 pack 布局所有的属性,但是不需要挨个熟悉,了解基本的即可。
pack 适用于简单的垂直或水平排布,如果需要复杂的布局可以使用 grid 或 place。
【示例】pack 布局用法,制作钢琴按键布局
# 测试pack布局管理 from tkinter import * root = Tk() root.geometry("700x220") root.title('钢琴按键分布') # 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,13): Label(f2,width=5,height=10,borderwidth=1,relief="solid", bg="black" if i%2==0 else "white").pack(side="left",padx=2) root.mainloop()
运行效果
3.place 布局管理器
place 布局管理器可以通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景。
Place 布局就是其他 GUI 编程中的“绝对布局”,这种布局方式要求程序显式指定每个组件的绝对位置或相对于其他组件的位置。
如果要使用 Place 布局,调用相应组件的 place() 方法即可。在使用该方法时同样支持一些详细的选项,关于这些选项的介绍如下:
【示例】place 布局管理-基本用法测试
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) #如果relx和x同时出现,先根据relx计算距离父组件最左边位置,然后再根据x来加减x像素的位置 Button(root,text="景天科技苑").place(relx=0.2,x=100,y=20,relwidth=0.2,relheight=0.5) Button(f1,text="百战程序员").place(relx=0.6,rely=0.7) Button(f1,text="景天老师").place(relx=0.5,rely=0.2) root.mainloop()
运行,景天科技苑按钮中,通过place布局,同时出现了x和relx,现根据relx计算相对于父组件的布局,然后再根据x来计算绝对布局
【示例】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) #10张牌的gif图片 #循环拿出扑克牌 self.photos = [PhotoImage(file="imgs/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)] #将10张扑克布局,折叠形式展示 for i in range(10): self.pukes[i].place(x=50+i*40,y=50) # 为所有的Label增加事件处理,<Button-1>表示单击左键 self.pukes[0].bind_class("Label","<Button-1>",self.chupai) def chupai(self,event): #event表示事件,包含了被点击的是哪个组件 #event.widget.winfo_geometry()表示组件的坐标信息 print(event.widget.winfo_geometry()) #event.widget.winfo_y()表示组件的y轴坐标信息 print(event.widget.winfo_y()) #点击鼠标出牌,如果未出牌,点击某张牌,该牌高度上移30,如果已出牌,就恢复到默认高度50 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") root.title('扑克牌游戏') app = Application(master=root) root.mainloop()
运行
点击某张牌,会上移
再点一下,会恢复