目录
GUI图形用户编程(三)
事件处理
一个GUI应用整个生命周期都处在一个消息循环(event loop)中,它等待事件的发生,并作出相应的处理。
Tkinter提供了用以处理相关事件的机制,处理函数可被绑定给各个控件的各种事件。
widget.bind(event,handler)
若相关事件发生,handler函数会被触发,事件对象event会传递给handler函数。
鼠标和键盘事件
代码 | 说明 |
---|---|
<Button-1>、<ButtonPress-1>、<1> | 鼠标左键按下,2表示中键,3表示右键 |
<ButtonRelease-1> | 鼠标左键释放 |
<B1-Motion> | 按住鼠标左键移动 |
<Double-Button-1> | 双击左键 |
<Enter> | 鼠标指针进入某一组件区域 |
<Leave> | 鼠标指针离开某一组件区域 |
<MouseWheel> | 滚动滑轮 |
<KeyPress-a> | 按下a键,a可用其他键代替 |
<KeyRelease-a> | 释放a键 |
<KeyPress-A> | 按下A键(大写的A) |
<Alt-KeyPress-a> | 同时按下alt和a,alt可用ctrl和shift替代 |
<Double-KeyPress-a> | 快速按两下a |
<Control-V> | CTRL和V键被同时按下,V可以换成其他键位 |
event对象常用属性
名称 | 说明 |
---|---|
char | 按键字符,仅对键盘事件有效 |
keycode | 按键编码,仅对键盘事件有效 |
keysym | 按键名称,仅对键盘事件有效。比如按下空格键:键的char ,键的keycode:32,键的keysym:apace。 |
num | 鼠标按键,仅对鼠标事件有效 |
type | 所触发的事件类型 |
widget | 引发事件的组件 |
width,height | 组件改变后的大小,仅Configure有效 |
x,y | 鼠标当前位置,相对于父容器 |
x—root, y—root | 鼠标当前位置,相对于整个屏幕 |
代码演示:
from tkinter import *
root =Tk()
root.geometry("530x300")
c1=Canvas(root,width=200,height=200,bg="blue")
c1.pack()
def mouseTest(event):
print("鼠标左键单击位置(相对于父容器):{0},{1}".format(event.x,event.y))
print("鼠标左键单击位置(相对于屏幕):{0},{1}".format(event.x_root,event.y_root))
print("事件绑定的组件:{0}".format(event.widget))
def testDrag(event):
c1.create_oval(event.x,event.y,event.x+1,event.y+1)
def keyboardTest(event):
print("键的keycode:{0},键的char:{1},键的keysym:{2}".format(event.keycode,event.keysym))
def press_a_test(event):
print("press a")
def release_a_test(event):
print("release a")
c1.bind("<Button-1>",mouseTest)
c1.bind("<B1-Motion>",testDrag)
root.bind("<KeyPress>",keyboardTest)
root.bind("<KeyPress-a>",press_a_test)
root.bind("<KeyRelease-a>",release_a_test)
root.mainloop()
lambda表达式详解
lambda表达式定义的是一个匿名函数,只适合简单输入参数,简单计算返回结果,不适合功能复杂的情况。
lambda定义的匿名函数也有输入,也有输出,只是没有名字,语法格式:
lambda 参数值列表:表达式
参数值列表即为输入,表达式计算的结构即为输出
简单案例:
add=lambda x,y,z:x+y+z
print(add(1,4,7))
#相当于
def add(x,y,z)
return x+y+z
lambda表达式的参数值列表
lambda格式 | 说明 |
---|---|
lambda x,y:x*y | 函数输入是x和y,输出的是它们的积x*y |
lambda :None | 函数没有输入参数,输出的参数None |
lambda : a(4,8) | 函数没有输入参数,输出的是a(4,8)的结果 |
lambda *args:sum(args) | 输入时任意个数的参数,输出是它们的和 |
lambda **args:1 | 输入的是任意键值对参数,输出是1 |
使用lambda表达式帮助command属性绑定时传参
from tkinter import *
#测试command属性绑定事件,测试lambda表达帮助传参
root=Tk()
root.geometry("270x50")
def mouseTest1():
print("command方式,简单情况:不涉及获取event对象,可以使用")
def mouseTest2(a,b):
print("a={0},b={1}".format(a,b))
Button(root,text="测试command1",command=mouseTest1).pack(side="left")
Button(root,text="测试command2",command=lambda:mouseTest2(4,8)).pack(side="left")
root.mainloop()
多种事件绑定方式汇总
组件对象的绑定
1.通过command属性绑定(适合简单不需获取event对象)
Button(root,text=“登录”,command=login)
2.通过bind()方法绑定(适合需要获取event对象)
c1=Canvas();c1.bind(“<Button-1>”,darwLine)
组件类的绑定
调用对象的bind—class函数,将该组件类的所有组件绑定事件:w.bind_class("Widget","event",eventhanler)
bnt01.bind_class("Button","<Button-1>",func)
多种事件绑定方式总结
from tkinter import *
#多种事件绑定方式汇总
root=Tk()
root.geometry("270x50")
def mouseTest1(event):
print("bind()方法绑定,可以获取event对象")
print(event.widget)
def mouseTest2(a,b):
print("a={0},b={1}".format(a,b))
print("command方法绑定,不能直接获取event对象")
def mouseTest3(event):
print("右击单击事件,绑定给所有按钮!")
print(event.widget)
b1=Button(root,text="测试bind()绑定")
b1.pack(side="left")
#bind方法绑定事件
b1.bind("<Button-1>",mouseTest1)
#command属性直接绑定事件
b2=Button(root,text="测试command2",command=lambda:mouseTest2(4,7))
b2.pack(side="left")
#给所有Button按钮都绑定右键单击事件<Button-2>
b1.bind_class("Button","<Button-2>",mouseTest3)
root.mainloop()