基本使用
基于tkinter创建 GUI基本四步:窗口->组件->布局->事件
1.创建窗口对象
from tkinter import *
root = Tk() # 创建窗口
root.mainloop() # 进入事件循环
2.创建组件
按钮文本等组件
btn = Button(root) # 创建Button组件,使组件在root窗口展示
btn['text'] = '我是按钮' # 组件属性参数
3.布局管理
管理组件的大小位置样式
btn.pack() # 布局管理器,组件的大小位置样式
4.事件
通过与组件绑定,获取组件所触发的事件
def btn_event(obj): # obj 即事件对象
print('控制台输出:'+'触发了事件') # 输出到控制台
btn.bind('<Button-1>', btn_event) # 事件和组件进行绑定
案例:
from tkinter import *
from tkinter import messagebox
root = Tk() # 创建窗口
btn = Button(root) # 创建Button组件,使组件在root窗口展示
btn['text'] = '我是按钮'
btn.pack() # 布局管理器,配置组件的样式
def btn_event(obj): # obj 即事件对象
messagebox.showinfo("Message","触发了事件") # 弹出新的窗口,并展示内容
print('控制台输出:'+'触发了事件') # 输出到控制台
btn.bind('<Button-1>', btn_event) # 事件绑定,事件和组件进行绑定 <Button-1> :鼠标左键点击一次 <Button-2>:鼠标右键点击一次
if __name__ == '__main__':
root.mainloop() # 进入事件循环
主窗口
title('窗口标题')
geometry('wxh ± x, ±y')
- w:宽度
- h:高度
- +x:距屏幕左边的距离,-x:距屏幕右边的距离
- +y:距屏幕上边的距离,-y:距;屏幕下边的距离
root.geometry('500x300+100+200') # 宽度500,高度300,距左边100,距上边200
组件
Toplevel | 顶层 | 容器类,可为其他组件提供单独的容器,类似窗口 |
Button | 按钮 | 按钮点击组件 |
Ganvas | 画布 | 提供绘图功能 |
Radiobutton | 单选框 | 单选框 |
CheckButton | 复选框 | 可勾选的复选框 |
Entry | 单行输入框 | 可输入内容 |
simpledialog其子方法 | 简单输入框 | |
filedialog其子方法 | 文件对话框 | 用于打开系统文件 |
Frame | 容器 | 用于装载其他组件 |
LabelFrame | 容器 | 类似Frame,但可以添加标题 |
label | 标签 | 显示不可编辑的文本或图标 |
Listbox | 列表框 | 可列出多个选项 |
Menu | 菜单 | 菜单组件 |
MenuButton | 菜单按钮 | 包含菜单的按钮,包括下拉层叠式等 |
OptionMenuu | 菜单按钮 | MenuButton的子类,可通过按钮打开一个菜单 |
Message | 消息框 | 可以显示多行文档 |
messagebox | 通用消息框 | 用于和用户简单的消息交互 |
Text | 文本框 | 可显示多行文本、图片、连接、HTML页面、CSS样式,甚至可添加组件等 |
Scale | 滑块 | 可移动滑块 |
askcolor | 颜色 |
Frame容器
GUI编程就是编写一个个组件,界面由组件组成,组件内又可以创建组件,这种组件即为容器
import tkinter as tk
from tkinter import Frame
root = tk.Tk()
root.title('包含容器的GUI')
root.geometry('500x300+200+200')
frame = Frame(master=root) # 在root中创建容器
frame.pack()
root.mainloop()
经典的面向对象的GUI
import tkinter as tk
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('经典的面向对象的GUI')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
self.btn01 = Button(self, text='容器的按钮01', command=self.btn01_event) # 创建button组件,在Frame中显示,这里的self是Frame
self.btn01.pack()
self.btn02 = Button(self, text='退出', command=root.destroy)
self.btn02.pack()
def btn01_event(self):
messagebox.showinfo('Message', '触发了事件')
print('控制台输出:' + '触发了事件') # 输出到控制台
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
Label
- font:字体和大小,1个中文宽度两个字符,高度一个字符
- image:图片,目前支持gif
- fg:前景色,bg:背景色
- justigy:对齐方式,left、center、right
- width:宽度,heigth:高度
import tkinter as tk
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
# 文件标签
self.text_label = Label(self, text='label组件',
width=10, height=2, bg='black', fg='white', font=('黑体', 15), justify='left', borderwidth=1)
self.text_label.pack()
self.text_label2 = Label(self, text='label组件\nlabel组件内容不能修改\n哈哈',
bg='black', fg='white', font=('黑体', 15), justify='left', borderwidth=1)
self.text_label2.pack()
# 图片标签
global PHOTO
PHOTO = PhotoImage(file='img.gif') # 注意:图片最好是全局变量
self.photo_label = Label(root, image=PHOTO)
self.photo_label.pack()
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
Button
import tkinter as tk
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
PHOTO = PhotoImage(file='img.gif') # 注意:图片最好是全局变量
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
self.login_btn = Button(self, text='登录', command=self.login_event) # 创建button组件,在Frame中显示,这里的self是Frame
self.login_btn.pack()
self.image_btn = Button(self, image=PHOTO, command=self.image_event)
self.image_btn.pack()
self.image_btn['state'] = 'disable' # 按钮禁止点击
def image_event(self):
messagebox.showinfo('Message', '点击了图片')
def login_event(self):
messagebox.showinfo('Message', '登录成功')
# print('控制台输出:' + '触发了事件') # 输出到控制台
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
Entry
import tkinter as tk
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
self.user_label = Label(self, text='用户')
self.user_label.pack()
user_value = StringVar() # 定义变量,要用来接收Entry输入的值
user_value.set('admin') # StringVar 的默认值
self.user_entry = Entry(self, textvariable=user_value) # StringVar变量绑定到Entry组件
self.user_entry.pack()
print(user_value.get())
print(self.user_entry.get())
self.pwd_label = Label(self, text='密码')
self.pwd_label.pack()
pwd_value = StringVar()
self.pwd_entry = Entry(self, textvariable=pwd_value, show="*") # 用户输入的内容展示成 *
self.pwd_entry.pack()
self.user_btn = Button(self, text='提交', command=self.login)
self.user_btn.pack()
def login(self):
print('用户名: ' + self.user_entry.get()) # 获取输入框的值
print('用户密码: ' + self.pwd_entry.get()) # 获取输入框的值
messagebox.showinfo('Message', '登录成功')
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
Text
- insert 插入内容到指定位置
- get 获取指定位置的内容
- image_create 插入图片到指定位置
- delete 删除指定位置的内容
- tag_add:添加标签 tag_config:标签样式 tag_bind:标签事件
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
self.text = Text(self, width=40, height=20, bg='gray') # width=40 宽度40,可显示20列汉字 height=20 高度20,可显示20行汉字
self.text.pack()
# 插入数据
self.text.insert(1.0, '123456\n') # inster 第一个参数为插入数据的坐标 x.y 1.0表示第一行第0列
Button(self, text='重复插入', command=self.insert_text).pack(side='left') # pack(side='left') 表示水平排列
Button(self, text='返回文本', command=self.return_text).pack(side='left')
Button(self, text='添加图片', command=self.add_image).pack(side='left')
Button(self, text='添加组件', command=self.add_widget).pack(side='left')
Button(self, text='通过tag精准控制文本', command=self.test_tag).pack(side='left')
def insert_text(self):
self.text.insert(INSERT, 'AAA') # INSERT 在光标所在位置插入内容
self.text.insert(END, 'BBB') # END 在文本末尾插入内容
def return_text(self):
print(self.text.get(1.0, 2.5)) # 获取指定范围内的文本, get(1.0, 2.5) 表示获取第1行第0列至地2行第5列的内容
print(self.text.get(1.0, END)) # 获取全部内容
def add_image(self):
self.photo = PhotoImage(file='img.gif')
self.text.image_create(END, image=self.photo)
def add_widget(self):
'''
在文本框中添加按钮组件
'''
btn = Button(self.text, text='按钮') # 添加的组件是在text组件中,所以一个参数是 self.text
self.text.window_create(INSERT, window=btn) # 将组件添加到 text组件中
def test_tag(self):
self.text.delete(1.0, END)
self.text.insert(1.0, '天净沙·秋思\n马致远\n枯藤老树昏鸦,\n小桥流水人家,\n古道西风瘦马。\n夕阳西下,断肠人在天涯\n')
# 添加 tag
self.text.tag_add('古诗名', 1.0, 1.6) # 第一个参数标签名,第二个参数标签范围
# 为标签添加样式
self.text.tag_config('古诗名', background='yellow', foreground='red', font=5)
self.text.insert(END, '百度')
# 为标签绑定事件
self.text.tag_add('baidu', 7.0, 7.2)
self.text.tag_config('baidu', underline=True)
self.text.tag_bind('baidu', '<Button-1>', self.go_baidu)
def go_baidu(self, event):
webbrowser.open('http://www.baidu.com')
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
Radiobutton
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
# 创建变量
self.gender = StringVar()
self.gender.set('F') # 设置默认值
# 变量与单选框绑定
self.rbtn1 = Radiobutton(self, text='男性', value='M', variable=self.gender).pack(side='left') # variable 将用户选择的值 value赋值给self.gender
self.rbtn2 = Radiobutton(self, text='女性', value='F', variable=self.gender).pack(side='left')
Button(self, text='确定', command=self.confirm).pack(side='left')
def confirm(self):
messagebox.showinfo('Message', '选择的性别为:'+self.gender.get())
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
Checkbutton
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
# 创建变量
self.code_hobby = IntVar()
self.video_hobby = IntVar()
print(self.code_hobby.get()) # 默认值为0
# Checkbutton onvalue选中时的值,offvalue未选中时的值, variable将值赋值给变量
self.cbtn1 = Checkbutton(self, text='代码', onvalue=1, offvalue=0, variable=self.code_hobby).pack(side='left')
self.cbtn2 = Checkbutton(self, text='电影', onvalue=1, offvalue=0, variable=self.video_hobby).pack(side='left')
Button(self, text='确定', command=self.confirm).pack(side='left')
def confirm(self):
hobby = []
if self.code_hobby.get() == 1:
hobby.append('代码')
if self.video_hobby.get() == 1:
hobby.append('电影')
messagebox.showinfo('Message', '选择的爱好:' + ','.join(hobby))
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
OptionMenu
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
self.value = StringVar()
self.value.set('python')
OptionMenu(self, self.value, 'python', 'go', 'java').grid(row=1, column=0)
Button(self, text='确定', command=self.language).grid(row=1, column=1)
def language(self):
print(self.value.get())
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
Menu
import tkinter as tk
import webbrowser
from tkinter import *
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
"""创建各种组件"""
# 创建菜单栏
main_menu = Menu(self.master)
# 创建子菜单栏
file_menu = Menu(main_menu, tearoff=0)
edit_menu = Menu(main_menu, tearoff=0)
help_menu = Menu(main_menu, tearoff=0)
# 将子菜单栏加入主菜单栏
main_menu.add_cascade(label='文件', menu=file_menu)
main_menu.add_cascade(label='编辑', menu=edit_menu)
main_menu.add_cascade(label='帮助', menu=help_menu)
# 添加菜单选项并绑定方法
file_menu.add_command(label='新建', accelerator='Ctrl+N', command=self.create_file)
file_menu.add_command(label='打开', accelerator='Ctrl+O', command=self.open_file)
file_menu.add_command(label='保存', accelerator='Ctrl+S', command=self.save_file)
file_menu.add_separator() # 添加分割线
file_menu.add_command(label='退出', command=root.quit)
# 将主菜单添加到窗口
self.master['menu'] = main_menu
def create_file(self):
pass
def open_file(self):
pass
def save_file(self):
pass
def main():
app = Application(master=root)
app.mainloop()
if __name__ == '__main__':
main()
Scale
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
"""创建各种组件"""
self.text_label = Label(self, text='好好学习', font=('宋体', 10))
self.text_label.pack()
Scale(
self,
from_=10, to=50, tickinterval=5, # 从10开始到50,按每份大小为5划分
length=200,
orient=HORIZONTAL, # HORIZONTAL:水平, 默认垂直
command=self.test
).pack()
def test(self, value):
# value 是滑块的值
print('滑块的值: ' + value)
font = ('宋体', value)
self.text_label.config(font=font)
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
askcolor
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter.colorchooser import askcolor
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
"""创建各种组件"""
Button(self, text='选择背景色', command=self.bgcolor).pack()
def bgcolor(self):
c = askcolor(title='选择背景色', color='red')
print(c[1])
root.config(bg=c[1])
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
filedialog文本对话框
方法包括:
askopenfilenames
:选择多个文件。- askopenfilename: 选中一个文件
askdirectory
:选择一个目录。asksaveasfilename
:选择一个文件保存位置。askopenfile
:打开一个文件并返回一个文件对象。asksaveasfile
:选择一个文件保存位置并返回一个文件对象
askopenfilename
参数:
title
:对话框的标题。initialdir
:初始目录。filetypes
:指定过滤的文件类型。defaultextension
:默认扩展名。
返回值:返回所选择文件的绝对路径,若选择的文件不存在则为空
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter.filedialog import *
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
"""创建各种组件"""
self.show_file_path = Label(self)
self.show_file_path.pack()
Button(self, text='上传文件', command=self.file_path).pack()
def file_path(self):
file = askopenfilename(title='上传文件', initialdir='/', filetypes=[('文本文件', '.txt')])
self.show_file_path['text'] = file
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
askopenfile
返回值:返回文件对象
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter.filedialog import *
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
"""创建各种组件"""
self.show_file_content = Label(self)
self.show_file_content.pack()
Button(self, text='上传文件', command=self.file_content).pack()
def file_content(self):
file = askopenfile(title='上传文件', initialdir='/', filetypes=[('文本文件', '.txt')])
self.show_file_content['text'] = file.read()
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
simpledialog简单输入框
要包含了以下几种对话框方法:
askstring(title, prompt, **options)
用户输入的字符串,如果用户点击了取消或关闭对话框,则返回None
askinteger(title, prompt, **options)
用户输入的整数,如果用户点击了取消或关闭对话框,则返回None
askfloat(title, prompt, **options)
用户输入的浮点数,如果用户点击了取消或关闭对话框,则返回None
参数:
title
:对话框的标题。prompt
:显示在对话框中的提示信息。**options
:其他选项,如initialvalue
、minvalue
、maxvalue
等。
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter.simpledialog import *
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
"""创建各种组件"""
self.show_name = Label(self)
self.show_name.grid(row=1, column=0)
Button(self, text='输入姓名', command=self.name).grid(row=1, column=1)
self.show_age = Label(self)
self.show_age.grid(row=2, column=0)
Button(self, text='输入年龄', command=self.age).grid(row=2, column=1)
def name(self):
v = askstring(title='输入姓名', prompt='请输入姓名')
self.show_name['text'] = v
def age(self):
v = askinteger(title='输入年龄', prompt='请输入年龄',
initialvalue=18, # 默认值
minvalue=1, maxvalue=150 # 大小范围
)
self.show_age['text'] = v
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
messagebox
包含的方法
showinfo(title, message, **options)
用于显示信息消息。showwarning(title, message, **options)
用于显示警告消息。showerror(title, message, **options)
用于显示错误消息。
askquestion(title, message, **options)
用于询问用户一个问题,并提供“是”和“否”两个选项。
askokcancel(title, message, **options)
用于询问用户一个问题,并提供“确定”和“取消”两个选项。
askyesno(title, message, **options)
用于询问用户一个问题,并提供“是”和“否”两个选项。
askretrycancel(title, message, **options)
用于询问用户是否重试,提供“重试”和“取消”两个选项。
askyesnocancel(title, message, **options)
用于询问用户一个问题,并提供“是”、“否”和“取消”三个选项。
参数:
title
:对话框的标题。message
:显示的信息内容。**options
:其他选项,如图标、按钮文本等。
案例
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
"""创建各种组件"""
Button(self, text='showinfo', command=self.showinfo).pack()
Button(self, text='showwarning', command=self.showwarning).pack()
Button(self, text='showerror', command=self.showerror).pack()
Button(self, text='askquestion', command=self.askquestion).pack()
Button(self, text='askokcancel', command=self.askokcancel).pack()
Button(self, text='askyesno', command=self.askyesno).pack()
Button(self, text='askretrycancel', command=self.askyesno).pack()
Button(self, text='askyesnocancel', command=self.askyesno).pack()
def showinfo(self):
messagebox.showinfo('消息提示', '这是一条提示消息')
def showwarning(self):
messagebox.showwarning("警告提示", "这是一个警告提示框。")
def showerror(self):
messagebox.showerror("错误提示", "这是一个错误提示框。")
def askquestion(self):
# # 询问问题(返回 'yes' 或 'no')
response = messagebox.askquestion("询问提示", "您确定要继续吗?")
if response == 'yes':
print("用户选择了 '是'。")
else:
print("用户选择了 '否'。")
def askokcancel(self):
# 询问问题(返回 True 或 False)
response = messagebox.askokcancel("询问提示", "您确定要继续吗?")
if response:
print("用户选择了 '确定'。")
else:
print("用户选择了 '取消'。")
def askyesno(self):
# 询问问题(返回 True 或 False)
response = messagebox.askyesno("询问提示", "您确定要继续吗?")
if response:
print("用户选择了 '是'。")
else:
print("用户选择了 '否'。")
def askretrycancel(self):
# 询问是否重试(返回 True 或 False)
response = messagebox.askretrycancel("询问提示", "操作失败,您想重试吗?")
if response:
print("用户选择了 '重试'。")
else:
print("用户选择了 '取消'。")
def askyesnocancel(self):
# 询问问题(返回 True、False 或 None)
response = messagebox.askyesnocancel("询问提示", "您确定要继续吗?")
if response is True:
print("用户选择了 '是'。")
elif response is False:
print("用户选择了 '否'。")
else:
print("用户选择了 '取消'。")
def main():
app = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
布局管理器
`tkinter` 提供了三种常用的布局管理器:`pack`、`grid` 和 `place`。每种布局管理器都有其独特的用途和特性,适用于不同的布局需求。
pack
`pack` 是一种基于容器的布局管理器,它将组件放置在父容器中的左侧、右侧、顶部或底部。使用 `pack` 时,组件可以扩展以填充可用空间,或者收缩以适应空间。这种布局方式非常适合那些不需要精确位置控制的简单界面。
- 组件可以扩展或收缩以适应容器大小的变化。
- 组件可以水平或垂直排列。
- 支持填充(fill)和扩展(expand)选项,使得组件可以占据更多的空间。
- 不适合需要精确坐标定位的情况。
常用参数:
- `side`:指定组件放置的位置,可以是 `TOP`、`BOTTOM`、`LEFT` 或 `RIGHT`。
- `expand`:布尔值,指定组件是否应该扩展以占据所有可用空间。
- `fill`:指定组件应该填充的方向,可以是 `X`、`Y` 或 `BOTH`。
grid
`grid` 布局管理器提供了一个表格形式的布局方式,可以将组件放置在一个二维网格中的单元格内。这种方式非常适合需要精确行和列定位的应用场景。
- 组件放置在一个由行和列组成的网格中。
- 每个组件占据一个或多个单元格。
- 支持跨越多个行或列的组件。
- 更适合复杂界面设计,尤其是表格式的布局。
常用参数:
- `row` 和 `column`:指定组件所在的行和列。
- `sticky`:指定组件如何对其所在单元格进行对齐,可以是 `N`、`S`、`E`、`W`、`NE`、`NW`、`SE`、`SW`、`NS`、`EW`、`NSW`、`NSE`、`NEW`、`NSEW`。
- `columnspan` 和 `rowspan`:指定组件跨越的行数和列数。
- `padx` 和 `pady`:指定组件周围的内部填充。
- `ipadx` 和 `ipady`:指定组件内部的填充。
案例
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
class Application(Frame):
def __init__(self, master):
super().__init__(master)
self.master = master
self.pack()
self.create_widget()
def create_widget(self):
'''创建各种组件'''
self.name = StringVar()
self.name.set('admin')
Label(self, text='账号').grid(row=1, column=0)
Entry(self, textvariable=self.name).grid(row=1, column=1)
self.pwd = StringVar()
Label(self, text='密码').grid(row=2, column=0)
Entry(self, textvariable=self.pwd).grid(row=2, column=1)
Button(self, text='登录', command=self.login).grid(row=3, column=0)
Button(self, text='退出', command=root.destroy).grid(row=3, column=1, sticky=E)
def login(self):
if self.name.get() == 'admin' and self.pwd.get() == '123456':
messagebox.showinfo('Message', '登录成功')
else:
messagebox.showinfo('Message', '用户名或密码错误')
def main():
app = Application(root)
rows, columns = root.grid_size()
print(f"Rows: {rows}, Columns: {columns}")
root.mainloop()
if __name__ == '__main__':
main()
place
`place` 布局管理器允许开发者以绝对坐标的形式来定位组件。这种方式最灵活但也最难维护,因为每个组件的位置都需要明确指定。
- 组件位置通过坐标 `(x, y)` 明确指定。
- 支持组件大小的精确控制。
- 适合需要高度定制化布局的设计。
- 由于绝对定位,可能导致布局在不同屏幕尺寸或分辨率下的表现不一致。
常用参数:
- `x` 和 `y`:指定组件左上角的坐标。
- `width` 和 `height`:指定组件的宽度和高度。
- `relx`、`rely` :相对父组件坐标进行定位(值范围:0-1)
- `relwidth`、`relheight`:相对父组件进行尺寸大小设置(值范围:0-1)。
案例
import tkinter as tk
from tkinter import *
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
f1 = Frame(root, width=300, height=200, bg='green')
f1.place(x=30, y=30) # f1 组件的左上角相对于其父组件(root)的距离 横向30,纵向30
Button(root, text='按钮1').place(
relx=0.2, # 相对父组件坐标 500 * 0.2
x=50, # relx 后面的 x属性 表示再向右移动
y=100,
relwidth=0.2, # 相对父组件宽度 500 * 0.2
relheight=0.5 # 相对父组件高度 300 * 0.5
)
Button(f1, text='按钮2').place(relx=0.1, rely=0.2)
root.mainloop()
选择合适的布局管理器
- 如果你的应用程序需要简单的布局,而且不需要精确的坐标定位,那么 `pack` 是一个很好的选择。
- 如果你需要一个表格形式的布局,其中每个组件的位置都可以精确控制,那么 `grid` 更适合你。
- 如果你需要绝对控制每个组件的位置和大小,那么 `place` 可以提供最大的灵活性,但也会带来更复杂的维护工作。
事件
组件绑定事件方法:
- widget.bind(event,handler) 当需要获取event对象时
- widget(commadn=handler) 当不需要获取event对象时
- widget.bind_class('Button',<Button-1>, func) 将所有Button绑定事件
当事件发生,handler函数会被出发,并将事件对象event传入
import tkinter as tk
from tkinter import *
root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')
def test1():
print('test1')
def test2(a, b):
print(a + b)
def test3(event):
print('test3')
# 适用事件函数不需要参数时
Button(root, text='按钮1', command=test1).pack(side='left')
# 适用事件函数需要参数时,利用lambda
Button(root, text='按钮2', command=lambda: test2(2, 5)).pack(side='left')
# 为所有Button按钮绑定鼠标右键事件
Button(root, text='按钮3').bind_class('Button', '<Button-2>', test3)
root.mainloop()
鼠标和键盘事件
event常用属性
ttk模块控件
特点
- 可定制性:
ttk
控件支持主题化,可以更容易地改变控件的外观。 - 跨平台一致性:
ttk
控件在不同操作系统上的外观更加一致。 - 更多的组件:
ttk
提供了一些tkinter
没有的组件,例如树形控件(Treeview)、进度条(Progressbar)等。
控件
ttk.Button
:按钮控件。ttk.Checkbutton
:复选框控件。ttk.Combobox
:下拉组合框控件。ttk.Entry
:输入框控件。ttk.Frame
:容器控件。ttk.Label
:标签控件。ttk.LabelFrame
:带标签的容器控件。ttk.Menubutton
:菜单按钮控件。ttk.PanedWindow
:窗格控件,用于创建分割窗口。ttk.Progressbar
:进度条控件。ttk.Radiobutton
:单选按钮控件。ttk.Scale
:滑动条控件。ttk.Separator
:分隔线控件。ttk.Sizegrip
:大小调整控件。ttk.Treeview
:树形表格控件。
案例
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.title('ttk 示例')
root.geometry('500x300+200+200')
# 创建一个 Frame 容器
frame = ttk.Frame(root, padding=10)
frame.pack(fill=tk.BOTH, expand=True)
# 创建一个 Label 标签
label = ttk.Label(frame, text="欢迎使用 ttk 控件!")
label.pack()
# 创建一个 Button 按钮
button = ttk.Button(frame, text="点击我")
button.pack()
# 创建一个 Entry 输入框
entry = ttk.Entry(frame)
entry.pack()
# 创建一个 Checkbutton 复选框
check_var = tk.BooleanVar()
checkbutton = ttk.Checkbutton(frame, text="同意协议", variable=check_var)
checkbutton.pack()
# 创建一个 Radiobutton 单选按钮
radio_var = tk.IntVar()
radiobutton1 = ttk.Radiobutton(frame, text="选项1", variable=radio_var, value=1)
radiobutton2 = ttk.Radiobutton(frame, text="选项2", variable=radio_var, value=2)
radiobutton1.pack()
radiobutton2.pack()
# 创建一个 Combobox 下拉组合框
combo = ttk.Combobox(frame, values=["选项A", "选项B", "选项C"])
combo.pack()
# 创建一个 Progressbar 进度条
progressbar = ttk.Progressbar(frame, length=200, mode='determinate')
progressbar.pack()
# 创建一个 Treeview 树形表格
tree = ttk.Treeview(frame, columns=("姓名", "年龄"), show='headings')
tree.heading("姓名", text="姓名")
tree.heading("年龄", text="年龄")
tree.insert("", tk.END, values=("张三", "25"))
tree.insert("", tk.END, values=("李四", "30"))
tree.pack()
root.mainloop()
《tkinter实用教程21》treeview 节点插入、单选、多选、事件、树、表格_tkinter treeview-CSDN博客