Tk的事件及功能绑定
- Tkinter 使用一种成为事件序列的机制来允许用户定义事件,用户需要bind()方法将具体的我事件序列与自定义的方法相绑定。
- 事件序列是以字符串的形式表示的。
- 可以表示一个或多个相关联的事件(如果是多个事件,那么对应的方法只有在满足所有的前提下才会被调用)。
事件序列使用一下语法描述:
<modifier-type-detail>
- 事件序列是包含在尖括号(<…>)中
- type必填,通常用于描述普通的事件类型,例如鼠标点击或键盘按键点击
- modifier可选,通常用于描述组合键,如Ctrl+c,Shift+鼠标左键
- detail可选,通常用于描述具体按键,如Button-1,表示鼠标左键
事件序列 | 含义 |
---|---|
<Button-1> | 鼠标左键 |
<Button-2> | 鼠标中键 |
<Button-3> | 鼠标右键 |
<KeyPress-H> | 用户点击 H 键 |
<Control-Shift-KeyPress-H> | 用户同时点击 Ctrl + Shift + H |
注意:button4、5用于linus系统的鼠标滚轮↑↓滑动,win和mac中用mouseview事件。
😃
type | 含义 |
---|---|
Active | 当组件状态从“未激活”变为“激活”时触发 |
Button | 当用户点击鼠标按键时触发 |
ButtonRelease | 1、当用户释放鼠标按键时触发 2、在大多数情况下,比Button更好用,用户不小心按下鼠标,可以移出组件外释放,则不会触发事件 |
Configure | 当组件尺寸改变时触发 |
Deactivate | 从“激活”变为“未激活”触发 |
Destroy | 当组建被销毁时触发 |
Enter | 1、当鼠标指针进入组件时触发 2、注意:不是指用户按下回车键(正确的写法是<Key-Return>) |
Expose | 当窗口或组建的某部分不再被覆盖时触发 |
FocusIn | 1、当组建获得焦点触发 2、用户按Tab将焦点转移到绑定的组件时触发(需要该组件的 takefocus 选项为 True) 3、直接使用 focus_set() 方法使组件获得焦点触发事件 |
FocusOut | 当组建失去焦点时触发 |
KeyPress | 1、当用户按下键盘按键时触发 2、detail可以指定具体的按键,例如/表示当大写的H键按下即会触发 3、KeyPress 可以简写为 Key |
KeyRelease | 当用户释放键盘按键时触发 |
Leave | 当鼠标指针离开组件时触发 |
Map | 1、当组件被映射时触发 2、意思是在应用程序中显示该组件时,例如调用grid()方法 |
Motion | 当鼠标在组件内移动的整个过程均触发 |
MouseWheel | 1、当鼠标滚轮滚动触发 2、目前该事件仅支持Win和Mac,Linus系统参考Button |
Unmap | 1、当组建被取消映射时触发 2、意思是应用程序中不再显示该组件时,例如调用grid_remove()方法 |
Visibility | 当应用程序至少有一部分在屏幕中是可见时触发 |
modifier
在事件序列中,modifier部分的内容可以是这些:
modifier | 含义 |
---|---|
Alt | 按下Alt键 |
Any | 1、表示任何类型的按键被按下的时候 2、例如表示用户按下任何按键时会触发事件 |
Control | 按下Ctrl键 |
Double | 1、当后两个事件被连续执行时触发 2、例如<Double-Button-1>表示当用户双击鼠标左键时触发 |
Lock | 当打开大写字母锁定键(CapsLock)时触发 |
Shift | 按下Shift键 |
Triple | 跟Double类似,当后续 3 个事件被连续执行时触发 |
Event对象
当Tkinter去回调你定义的函数时,都会带着Event对象(作为参数)去调用,Event对象一下这些属性可以调用:
属性 | 含义 |
---|---|
Widget | 产生该事件的组件 |
x,y | 当前鼠标位置(窗口左上角为(0,0)) |
x_root,y_root | 当前鼠标位置(窗口左上角为(0,0)) |
char | 按键对应的字符(键盘事件专属) |
keysym | 按键名,见下方Key names(键盘事件专属) |
keycode | 按键名,见下方Key names(键盘事件专属) |
num | 按钮数字(鼠标事件专属) |
width,height | 组件的新尺寸(Configure事件专属) |
type | 该事件的类型 |
Key names
当事件为<key>,<KeyPress>,<KeyRelease>的时候,detail 可以通过设定具体的按键名(keysym)来筛选。例如<Key-H>表示按下键盘上的大写字母H时触发,<Key-Tab>表示按下键盘的Tab按键时触发。
按键名(keysym) | 按键码(keycode) | 代表的按键 |
---|---|---|
Alt_L | 64 | 左 Alt键 |
Alt_R | 113 | 右 Alt键 |
BackSpace | 22 | 退格键 |
Cancel | 110 | break键 |
Caps_Lock | 66 | 大小写切换键 |
Control_L | 37 | 左Ctrol键 |
Control_R | 109 | 右Ctrol键 |
Delete | 107 | 删除键 |
Down | 104 | ↓按键 |
End | 103 | End键 |
Escape | 9 | Esc键 |
Execute | 111 | SysReq键 |
F1 | 67 | F1键 |
F2 | 68 | F2键 |
F3 | 69 | F3键 |
F4 | 70 | F4键 |
F5 | 71 | F5键 |
F6 | 72 | F6键 |
F7 | 73 | F7键 |
F8 | 74 | F8键 |
F9 | 75 | F9键 |
F10 | 76 | F10键 |
F11 | 77 | F11键 |
F12 | 96 | F12键 |
Home | 97 | Home键 |
Insert | 106 | Insert键 |
Left | 100 | ←按键 |
Linefeed | 54 | Linefeed(Ctrl + j) |
Next | 105 | PageDown 按键 |
Prior | 99 | PageUp 按键 |
Pause | 110 | Pause(暂停)按键 |
111 | PrintScrn(打印屏幕)按键 | |
Return | 36 | Enter(回车)键 |
Right | 102 | →按键 |
Scroll_Lock | 78 | ScrollLock 按键 |
Shift_L | 50 | 左Shift键 |
Shift_R | 62 | 右Shift键 |
Tab | 23 | Tab键 |
Up | 98 | ↑键 |
小键盘的 keysym 和 keycode 对照:
Num_Lock (77) | KP_Divide (??) | KP_Multiply (63) | KP_Subtract (82) |
KP_7 / KP_Home (79) | KP_8 / KP_Up (80) | KP_9 / KP_Prior (81) | KP_Add 86 |
KP_4 / KP_Left (83) | KP_5 / KP_Begin (84) | KP_6 / KP_Right (85) | |
KP_1 / KP_End (87) | KP_2 / KP_Down (88) | KP_3 / KP_Next (89) | KP_Enter (108) |
KP_0 / KP_Insert (90) | KP_Decimal / KP_Delete (91) |
简单事件例子:
from tkinter import *
class App:
def __init__(self, master):
f1 = Frame(master, width=200, height=200, bg='#fff')
f1.pack(padx=5, pady=5)
var = StringVar()
var.set('Hell')
lb = Label(master, textvariable=var)
lb.pack(padx=5, pady=5)
# self.appPos(f1, var)
self.kEyboard(f1, var)
# self.appPos2(f1, var)
def appPos(self, frame, var):
frame.bind('<Button-1>', lambda p: var.set(f'点击位置, {p.x}, {p.y}'))
def kEyboard(self, frame, var):
# frame.bind('<Key>', lambda p: print('单击的按键是:', p.char))
# frame.bind('<Key>', lambda p: print(p.char, end=''))
# frame.bind('<Key>', lambda event: var.set(f'单击的按键是:{event.char}'))
# .char 也可以切换成 .keysym
frame.bind('<Key>', lambda event: var.set(f'单击的按键是:{event.keysym}'))
frame.focus_set() # 这句不加也没报错,正常可以输出字符
def appPos2(self, frame, var):
def callback1(event):
print('\b' * 9, end='', flush=True)
print(event.x, event.y, end='')
# frame.bind('<Motion>', callback1)
var.set('显示当前坐标')
frame.bind('<Motion>', lambda event: var.set(f'当前坐标:{event.x},{event.y}'))
frame.bind('<Leave>', lambda event: var.set('请把鼠标移进程序里'))
if __name__ == '__main__':
root = Tk()
root.title('TkPainter')
app = App(root)
root.mainloop()
![]() | ![]() | ![]() |
---|
Message & SpinBox & PanedWindow & Toplevel
from tkinter import *
class App:
def __init__(self, master):
self.mSg(master)
# self.sPinbox(master)
# self.pWindow1(master)
# self.pWindow2(master)
# self.topLevel(master)
def mSg(self, master):
Message(master, text='这是一则消息', width=100).pack()
Message(master, text='这是一则\n骇人听闻的长长长长长长长长长消息!', width=100).pack()
def sPinbox(self, master):
Spinbox(master, from_=0, to=10, increment=0.5, wrap=TRUE).pack()
Spinbox(master, values=('harry', '~ben~', 'lily_w', '黄小明'), wrap=TRUE).pack()
def pWindow1(self, master):
m = PanedWindow(master, orient=VERTICAL)
m.pack(fill=BOTH, expand=1)
top = Label(m, text='top pane', bg='#E83399')
m.add(top)
bottom = Label(m, text='bottom pane', bg='#23E667')
m.add(bottom)
def pWindow2(self, master):
m1 = PanedWindow(master, showhandle=TRUE, sashrelief=SUNKEN)
m1.pack(fill=BOTH, expand=1)
left = Label(m1, text='left pane')
m1.add(left)
m2 = PanedWindow(orient=VERTICAL, showhandle=TRUE, sashrelief=SUNKEN)
m1.add(m2)
top = Label(m2, text='top pane', bg='#E83399')
m2.add(top)
bottom = Label(m2, text='bottom pane', bg='#23E667')
m2.add(bottom)
def topLevel(self, master):
def create():
top = Toplevel()
top.attributes('-alpha', 0.5)
top.title('Baby message')
Message(top, text='I love you Hunny').pack()
Button(master, text='创建顶级窗口', command=create).pack()
if __name__ == '__main__':
root = Tk()
root.title('TkPainter')
app = App(root)
root.mainloop()
![]() | ![]() | ![]() | ![]() |
---|