GUI介绍
GraphicalUserInterface
,简称GUI–图形化界面
python的GUI
: Tkinter
, wxPython
, PyQt
TKinter
:
- Python标准库,绑定的是
TK GUI工具集
,简单易用
PyGTK
:
wxPython
:
PyQt
:
Tkinter常用组件
- 按钮
Button
按钮组件RadioButton
单选框组件CheckButton
选择按钮组件Listbox
列表框组件
- 文本输入组件
Entry
单行文本框组件Text
多行文本框组件
- 标签组件
Label
标签组件,可以显示图片和文字Message
标签组件,可以根据内容将文字换行
- 菜单
Menu
菜单组件MenuButton
菜单按钮组件,可以使用Menu
代替
- 滚动条
scale
滑块组件Scrollbar
滚动条组件
- 其他组件
Canvas
画布组件Frame
框架组件,将多个组件编组Toplevel
创建子窗口容器组件
---label实例---
import tkinter
base = tkinter.Tk()
base.wm_title("Label Test")
lb = tkinter.Label(base, text="Python Label")
lb.pack()
base.geometry("500x500+200+50")
base.mainloop()
---设置label实例---
import tkinter
base = tkinter.Tk()
base.wm_title("Label Test")
lb1 = tkinter.Label(base, text="Python AI")
lb1.pack()
lb2 = tkinter.Label(base, text="绿色背景", background="green")
lb2.pack()
lb3 = tkinter.Label(base, text="蓝色背景", background="blue")
lb3.pack()
base.mainloop()
---窗口居中显示---
import tkinter
win = tkinter.Tk()
sw = win.winfo_screenwidth()
sh = win.winfo_screenheight()
ww = 500
wh = 100
x = (sw-ww) / 2
y = (sh-wh-50) / 2
win.geometry("%dx%d+%d+%d" % (ww, wh, x, y))
win.mainloop()
组件的大致使用步骤
- 创建总面板
- 创建面板上的各种组件
- 指定组件的父组件,即依附关系
- 利用相应的属性对组件进行设置
- 给组件安排布局
- 同步骤2相似,创建好多个组件
- 最后,启动总面板的消息循环
---Button实例---
import tkinter
def showLabel():
global baseFrame
lb = tkinter.Label(baseFrame, text="显示Label")
lb.pack()
baseFrame = tkinter.Tk()
btn = tkinter.Button(baseFrame, text="Show Label", command=showLabel)
btn.pack()
baseFrame.mainloop()
Button
的属性:
anchor
设置按钮中文字的对其方式,相对于按钮的中心位置background(bg)
设置按钮的背景颜色foreground(fg)
设置按钮的前景色(文字的颜色)borderwidth(bd)
设置按钮边框 宽度cursor
设置鼠标在按钮上的样式command
设定按钮点击时触发的函数bitmap
设置按钮上显示的位图font
设置按钮上文本的字体width
设置按钮的宽度(字符个数)height
设置按钮的高度(字符个数)state
设置按钮的状态text
设置按钮上的文字image
设置按钮上的图片
组件布局
- 控制组件的摆放方式
- 三种布局:
pack
: 按照方位布局,即按添加顺序排列组件grid
: 网格布局,即按行列形式排列组件place
: 按照坐标布局,能够实现自定义排列组件- 注意:
不要在同一个父组件中同时使用 pack 和 grid
pack
布局
- 最简单,代码量最少,挨个摆放,默认从上到下,系统自动设置(适用于
少量组件
或简单布局
) - 基本格式:
组件对象.pack()
side
:停靠方位,可选值为LEFT,TOP,RIGHT,BOTTOM
fill
: 填充方式X(水平), Y(垂直), BOTH(水平和垂直), NONE(默认)
expande
: YES/NO
anchor
: N,E,S,W, CENTER
ipadx
: 水平方向的内边距ipady
: 垂直方向的内边距padx
: 水平方向外边距pady
: 垂直方向外边距
grid
布局
- 把整个窗口看成一个网格,通过
行和列
来指定位置,适用于对话框一类的布局 - 基本格式:
组件对象.grid(row,column...)
- 利用
row,column
编号,即行号
和列号
sticky
:N,E,S,W
表示上下左右,用来决定组件的对齐方向ipadx
: 水平方向的内边距ipady
: 垂直方向的内边距padx
: 水平方向外边距pady
: 垂直方向外边距rowspan
: 表示跨行,跨行数量columnspan
: 表示跨列,跨列数量
place
布局(不常用)
- 虽然能够实现自定义排列组件,但使用起来过于复杂,还容易出现重叠
- 使用
place
布局,分为绝对布局
和相对布局
- 相对布局
使用relx,rely,relheight,relwidth
- 绝对布局
使用x,y
参数
---pack基本布局案例---
import tkinter as tk
baseFrame = tk.Tk()
tk.Label(baseFrame, text="Red", bg="red", fg="white").pack()
tk.Label(baseFrame, text="Blue", bg="blue", fg="white").pack()
tk.Label(baseFrame, text="Green", bg="green", fg="white").pack()
tk.Label(baseFrame, text="Yellow", bg="yellow", fg="black").pack()
---账号登录(grid)实例---
import tkinter
def register(event):
user = userNameEntry.get()
pwd = pwdEntry.get()
t1 = len(user)
t2 = len(pwd)
if user == "root" and pwd == "123456":
statusLabel['text'] = "登录成功"
else:
statusLabel['text'] = "用户名或密码错误"
userNameEntry.delete(0, t1)
pwdEntry.delete(0,t2)
psd = tkinter.Tk()
userName = tkinter.Label(psd, text="用户名")
userName.grid(row=0, sticky=tkinter.W)
userNameEntry = tkinter.Entry(psd)
userNameEntry.grid(row=0, column=1, sticky=tkinter.E)
pwd = tkinter.Label(psd, text="密码")
pwd.grid(row=1, column=0, sticky=tkinter.W)
pwdEntry = tkinter.Entry(psd)
pwdEntry['show'] = '*'
pwdEntry.grid(row=1, column=1, sticky=tkinter.E)
loginBtn = tkinter.Button(psd, text="登录", command=register)
loginBtn.grid(row=2, column=1, sticky=tkinter.E)
psd.bind('<Return>', register)
statusLabel = tkinter.Label(psd, text='')
statusLabel.grid(row=3)
psd.mainloop()
三种标准对话框
提示消息对话框
- 导入模块:
from tkinter import messagebox
- 警告对话框
.showinfo()
:蓝感叹号警告
.showwarning()
:黄三角警告
.askretrycancel()
:黄三角警告
- 错误对话框
- 询问对话框
.askquestion()
:询问
.askokcancel()
:询问
.askyesno()
:询问
.askyesnocancel()
:询问
- 选项:
是
、否
、取消
- 返回值:
Ture
、Flase
、None
- 全部对话框的参数
对话框类型(title, message, default, icon, parent)
title
:对话框标题message
:对话框内容default
:设置按回车键执行的按钮CANCEL,IGNORE,OK,NO,RETRY 或 YES
icon
:对话框图标ERROR,INFO,QUESTION 或 WARNING
parent
:…不常用,有兴趣自行了解
---对话框实例---
from tkinter import messagebox
res = messagebox.askquestion(title='问候一下', message='您吃饭了吗?')
print(res)
文件相关对话框
- 导入模块:
from tkinter import filedialog
.askopenfilename()
:选择文件名
.askdirectory()
:选择目录名
.asksaveasfilename()
:保存文件
- 全部文件相关的参数
defaultextension
:指定保存文件的文件后缀filetypes
:指定筛选下拉菜单的类型initialdir
:默认的打开路径title
:对话框的标题parent
:…不常用,有兴趣自行了解
- 注意:
如果用户点击了取消按钮,那么返回值是空字符串
---图片另存实例---
import tkinter as tk
from tkinter import filedialog as fd
from PIL import Image
def selectFile():
global img,filepath
filepath = fd.askopenfilename(title="选择要另存的图片")
filename.set(filepath)
img = Image.open(filename.get())
def outputFile():
outputFilePath = fd.askdirectory(title="选择需要另存的目录")
outputpath.set(outputFilePath)
def fileSave():
extension = "." + filepath.split(".")[-1]
filenewpath = fd.asksaveasfilename(title="设置要保存的图片名", defaultextension=extension)
filenewname.set(filenewpath)
img.save(str(filenewname.get()))
save_image = tk.Tk()
save_image.wm_title("保存图片")
filename = tk.StringVar()
outputpath = tk.StringVar()
filenewname = tk.StringVar()
tk.Label(save_image, text='选择图片').grid(row=1, column=0, padx=5, pady=5)
tk.Entry(save_image, textvariable=filename).grid(row=1, column=1, padx=5, pady=5, ipadx=50)
tk.Button(save_image, text='打开图片', command=selectFile).grid(row=1, column=2, padx=5, pady=5)
tk.Label(save_image, text='选择目录').grid(row=2, column=0, padx=5, pady=5)
tk.Entry(save_image, textvariable=outputpath).grid(row=2, column=1, padx=5, pady=5, ipadx=50)
tk.Button(save_image, text='点击选择', command=outputFile).grid(row=2, column=2, padx=5, pady=5)
tk.Label(save_image, text='保存文件').grid(row=3, column=0, padx=5, pady=5)
tk.Entry(save_image, textvariable=filenewname).grid(row=3, column=1, padx=5, pady=5, ipadx=50)
tk.Button(save_image, text='点击保存', command=fileSave).grid(row=3, column=2, padx=5, pady=5)
save_image.mainloop()
颜色相关对话框
- 导入模块:
from tkinter import colorchooser
.askcolor()
:颜色选择器
- 返回值:元组类型 -> (16进制颜色码, (R, G, B))
- 颜色选择器参数
color
:要显示的初始的颜色title
:颜色选择器的标题parent
:…不常用,有兴趣自行了解
---颜色选择器实例---
import tkinter as tk
from tkinter import colorchooser
root = tk.Tk()
def color_choose():
color_data = colorchooser.askcolor()
print(color_data)
tk.Button(root, text='选择颜色', command=color_choose).pack()
tk.mainloop()
显示图片
tkinter.PhotoImage(file='图片路径')
- 导入其他类型的图片
- 导入模块:
from PIL import Image, ImageTk
- 导入图片,设置图片大小:
img = Image.open('xx.jpg').resize((200, 200))
- 加载进tkinter画布:
photo = ImageTk.PhotoImage(img)
---背景图实例---
import tkinter as tk
from PIL import Image, ImageTk
baseFrame = tk.Tk()
baseFrame.wm_title("背景图实例")
img = Image.open('20.jpg').resize((200, 200))
photo = ImageTk.PhotoImage(img)
theLabel = tk.Label(baseFrame, text="我是内容,\n请你阅读",
justify=tk.LEFT,
image=photo,
compound=tk.CENTER,
font=("华文行楷", 20),
fg="white")
theLabel.pack()
tk.mainloop()
消息机制
- 消息的传递机制
- 自动发出事件/消息
- 消息有系统负责发送到队列
- 由相关组件进行绑定/设置
- 后端自动选择感兴趣的事件并做出相应反应
- 消息格式
<[modifier-]-typer-[-detail]>
<Button-1>
: Button表示一个按钮事件,1代表鼠标左键,2代表中键, 3代表右键<KeyPress-A>
: 键盘A键位<Control-Shift-KeyPress-A>
: 同时按下Control, Shift, A三个键位<F1>
: F1键位
- 全部键位对应名称
---点击事件实例---
import tkinter
def baseLabel(event):
global baseFrame
lb = tkinter.Label(baseFrame, text="你点我干嘛...")
lb.pack()
baseFrame = tkinter.Tk()
baseFrame.wm_title("点击事件实例")
lb = tkinter.Label(baseFrame, text="模拟按钮")
lb.bind("<Button-1>", baseLabel)
lb.pack()
baseFrame.mainloop()
Tkinter的绑定
bind_all
: 全局范围的绑定,默认的是全局快捷键,比如F1是帮助文档bind_class
:接受三个参数,第一个是类名,第二个是事件,第三个是操作bind
:单独对某一个实例绑定unbind
:解绑,需要一个参数,即你要解绑的那个事件
菜单
- 普通菜单
Menu()
定义的是parent(父类菜单)
- 第一个参数:
需要绑定菜单的窗口对象
tearoff
:菜单是否能被撕下(默认为True)
add_ command()
: 添加菜单项,如果菜单是顶层菜单,则从左向右添加,否则就是下拉菜单
label
: 指定菜单项名称command
: 点击后相应的调用函数acceletor
: 快捷键underline
: 制定是否菜单信息下有横线menu
: 属性制定使用哪-一个作为顶级菜单
---普通菜单实例---
import tkinter
baseFrame = tkinter.Tk()
baseFrame.wm_title("普通菜单实例")
menubar = tkinter.Menu(baseFrame, tearoff=False)
for item in ['菜单1', '菜单2', '菜单3', '菜单4']:
menubar.add_command(label=item)
baseFrame['menu'] = menubar
baseFrame.mainloop()
- 级联菜单
add_ cascade()
: 级联菜单,作用是引出后面的菜单add_ cascade()
的menu属性
: 指明把菜单级联到哪个菜单上
label:
需要显示的名称- 级联菜单的创建过程:
建立menu实例
-> add_command
-> add_cascade
---级联菜单实例---
import tkinter
baseFrame = tkinter.Tk()
baseFrame.wm_title("级联菜单实例")
menubar = tkinter.Menu(baseFrame)
e_menu = tkinter.Menu(menubar)
for item in ['Copy', 'Past', 'Cut']:
e_menu.add_command(label=item)
menubar.add_cascade(label='File')
menubar.add_cascade(label='Edit', menu=e_menu)
menubar.add_cascade(label='About')
baseFrame['menu'] = menubar
baseFrame.mainloop()
- 弹出式菜单
- 弹出菜单也叫上下文菜单
- 实现的大致思路
- 建立菜单并向菜单添加各种功能
- 监听鼠标右键
- 如果右键点击,则根据位置判断弹出
- 调用menu的pop方法
add_separator()
: 添加分隔符
---弹出式菜单实例---
import tkinter
def makeLabel():
global baseFrame
tkinter.Label(baseFrame, text="PHP是最好的编程语言,我用Python").pack()
baseFrame = tkinter.Tk()
baseFrame.wm_title("弹出式菜单实例")
menubar = tkinter.Menu(baseFrame)
for x in ['麻辣香菇', '气锅鸡', '东坡肘子']:
menubar.add_separator()
menubar.add_command(label=x)
menubar.add_command(label='重庆火锅', command=makeLabel)
def pop(event):
menubar.post(event.x_root, event.y_root)
baseFrame.bind("<Button-3>", pop)
baseFrame.mainloop()
canvas-画布
- 画布: 可以自由的在上面绘制图形的一个小舞台
- 在画布上绘制对象,通常用
create_xxXX, xxxx=
对象类型,例如line, rectangle - 画布的作用是把一定组件画到画布上显示出来
- 画布所支持的组件:
arc
bitmap
image(BitmapImage, PhotoImage)
line
oval
polygon
rectangle
text
winodw(组件)
- 每次调用
create_xxx
都会返回一个创建的组件的ID,同时也可以用tag属性指定其标签 - 通过调用
canvas.move
实现一个一次性动作
---画布实例---
import tkinter
baseFrame = tkinter.Tk()
baseFrame.wm_title("画布实例")
cvs = tkinter.Canvas(baseFrame, width=300, height=200)
cvs.pack()
cvs.create_line(23,23, 190,234)
cvs.create_text(56,67, text="I LOVE PYTHON")
baseFrame.mainloop()
---五角星实例---
import tkinter
import math as m
baseFrame = tkinter.Tk()
baseFrame.wm_title("五角星实例")
w = tkinter.Canvas(baseFrame, width=300, height=300, background="gray")
w.pack()
center_x = 150
center_y = 150
r=150
points = [
center_x - int(r * m.sin(2 * m.pi / 5)),
center_y - int(r * m.cos(2 * m.pi / 5)),
center_x + int(r * m.sin(2 * m.pi / 5)),
center_y - int(r * m.cos(2 * m.pi / 5)),
center_x - int(r * m.sin( m.pi / 5)),
center_y + int(r * m.cos( m.pi / 5)),
center_x,
center_y - r,
center_x + int(r * m.sin(m.pi / 5)),
center_y + int(r * m.cos(m.pi / 5)),
]
w.create_polygon(points, outline= "green", fill="yellow")
w.create_text(150,150, text="五角星")
baseFrame.mainloop()
---动画实例---
import tkinter
baseFrame = tkinter.Tk()
baseFrame.wm_title("动画实例")
def btnClick(event):
global w
w.move(id_ball, 12,5)
w.move("fall", 0,5)
w = tkinter.Canvas(baseFrame, width=500, height=400)
w.pack()
w.bind("<Button-1>", btnClick)
id_ball = w.create_oval(20,20,50,50, fill="green")
w.create_text(123,56, fill="red", text="ILovePython", tag="fall")
id_rectangle = w.create_rectangle(56,78,173,110, fill="gray")
w.addtag_withtag("fall", id_rectangle)
baseFrame.mainloop()