五笔打字通主页
我们做的GUI程序,即有界面的程序,都是事件驱动的程序,就是说,当有鼠标点击时,或键盘健入,或窗体组件大小位置改变时,程序就会发生相应的动作。tkinter也提供了一些事件处理程序让我们利用,比如,我们已经学过的按钮等组件,就用一个command参数,它会绑定一个函数,当我们点击这个按钮时,程序就会调用函数,让程序做出相应的反应。
但是,有些组件没有command这个属性,例如你当点击标签时,程序如何做出相应的反应?今天就讲一讲事件及绑定的事,即让所有组件都可以绑定一个或多个函数,让窗体或组件可以在鼠标或键盘等事件发生时,做出相应的反应。
首先就来讲一下,如何让标签在鼠标点击后,也会有动作。让大家对tkinter的事件绑定有一个初步的了解。
先来讲一下语法:
组件.bind(事件,绑定的函数)
以下是标签绑定一个函数,也可以响应鼠标点击事件的代码:
from tkinter import * def clik(event): : # 一定要加参数event root.config(bg='blue') root=Tk() root.geometry('200x100+888+444') la1=Label(root,text='点击我看看',relief='groove') la1.pack() la1.bind("<Button-1>",clik) # 标签la1,鼠标左键点击,调用clik函数 root.mainloop()
运行后,鼠标左键点击标签,窗体背景颜色变蓝。
以上代码要注意一点,bind绑定事件的函数一定要加上参数,参数默认取名是event,当然你也可以取别的参数名称。
事件绑定函数,成功地让没有command属性的标签也可以拥有鼠标点击反应的能力。按钮等拥有command属性的组件,也同样可以通过事件绑定,让按钮等组件拥有更多的事件反应能力。
按钮组件可以通过command参数绑定一个函数了,但下面代码可以为按钮再增加一些事件的反应能力。
from tkinter import * def clik1(): print('command绑定函数') def clik2(event): # 一定要加参数event print('bind绑定函数1') def double_clik(event): # 一定要加参数event print('我被双击了') root=Tk() root.geometry('200x100+888+444') but1=Button(root,text="点击",command=clik1) but1.pack() but1.bind("<Button-1>",clik2) # 鼠标左键点击绑定函数 but1.bind("<Double-Button-3>",double_clik) # 鼠标右键双击绑定函数 root.mainloop()
以上代码,我为按钮but1绑定了 3个事件函数,1是通过command绑定函数clik1,2是通过bind方法为按钮接受鼠标左键单击和鼠标右键双击绑定函数。
运行后,用鼠标点击按钮后,首先输出:“bind绑定函数1” 然后再输出:“command绑定函数”,由此可见,由bind方法绑定的函数有优先调用权。
我们再用鼠标右键双击按钮,会输出“我被双击了”,可见,按钮因此增加了对鼠标双击反应的能力。同样道理,我们还可以为按钮或其它组件增加鼠标右键单击,双击事件反应功能,鼠标移动事件反应功能,键盘事件反应功能…………
上面的代码,我们已经用bind方法为鼠标左键单击事件绑定了函数clik2,如果再用用bind方法为鼠标左键单击事件绑定了函数clik3会怎么样?代码如下:
from tkinter import * def clik1(): print('command绑定函数') def clik2(event): # 一定要加参数event print('bind绑定函数1') def clik3(event): # 一定要加参数event print('bind绑定函数2') def double_clik(event): # 一定要加参数event print('我被双击了') root=Tk() root.geometry('200x100+888+444') but1=Button(root,text="点击",command=clik1) but1.pack() but1.bind("<Button-1>",clik2) # 鼠标左键点击绑定函数 but1.bind("<Button-1>",clik3) # 鼠标左键点击绑定函数 but1.bind("<Double-Button-3>",double_clik) # 鼠标右键双击绑定函数 root.mainloop()
运行后,点击按钮,发现不会输出“bind绑定函数1”,只会输出“bind绑定函数2”,由此可见,后面的事件绑定完全取代了前面的事件绑定。
其实,bind方法还有第3个参数add,它默认为“”,如果add="+” ,那么,以后的事件绑定不会代替以前的事件绑定,2个事件绑定都可以起作用。我们用
but1.bind("<Button-1>",clik3) # 鼠标左键点击绑定函数
改成
but1.bind("<Button-1>",clik3,add="+") # 鼠标左键点击绑定函数
运行后,点击按钮,发现2个函数都可以运行并输出。
tkinter事件按大类来分,分为:键盘事件,鼠标事件以及组件大小,位置,状态变化事件3大类。我们先了解一下事件的写法格式:
我们前面有代码是绑定鼠标双击事件,写法是:”<Double-Button-1>” 我以此为例来说明事件写法格式,tkinter事件用置于尖号(<>)内的一串字符串来表示,其通用格式是:
“<[modifier-]…type[-detail]>”
modifier:这个前缀修饰用于组合键定义,是可选的。
type:表示事件通用类型,是必选的
detail:这个后缀细节,用于具体的信息。
例如:”<Double-Button-1>” 鼠标左键双击事件
Double是前缀,表双击
Button是事件通用类型,表示鼠标按键事件
1是后缀,表细节,表示是鼠标左键按下。
再如:”<Control-Shift-Alt-KeyPress-A>” 表示同时按下Ctrl,Shitf,Alt, A四个键
Control-Shift-Alt 是前缀,表示键盘击打按键时,还按下了其它3个组合键
KeyPress 是通用事件,即键盘击打事件,必选
A 是后缀细节,表示键位A (注意,键盘事件后缀是区分大小写的
以上的例子,就知道各种组合事件很多,无法一一举例,所以,我先来说一下必选的通用事件类型(type)
Type | 事 件 | 说明 | |||
键盘 事件 | 2 | KeyPress | 按下键盘时触发,可简写为Key | ||
3 | KeyRelease | 释放键盘时触发 | |||
鼠标 事件 | 4 | Button | 按下鼠标时触发 | ||
5 | ButtonRelease | 释放鼠标时触发 | |||
6 | Motion | 鼠标按下并拖拽组件移动触发 | |||
7 | Enter | 鼠标指针进入某个组件触发 | |||
8 | Leave | 鼠标指针离开某个组件触发 | |||
38 | MouseWheel | 鼠标滚轮滚动时触发 | |||
窗体 事件 | 15 | Visibility | 组件变为可视状态时触发 | ||
18 | Unmap | 组件由显示状态变隐藏状态时触发 | |||
19 | Map | 组件由隐藏状态变显示状态时触发 | |||
12 | Expose | 组件从其它组件遮盖中暴露出来触发 | |||
9 | FocusIn | 组件获得焦点时触发 | |||
10 | FocusOut | 组件失去焦点时触发 | |||
22 | Configure | 组件大小发生改变时触发 | |||
36 | Activate | 组件状态由不可用转为可用时触发 | |||
37 | Deactivate | 组件状态由可用转为可用 | |||
Property | 窗体属性被删除或改变,TK核心 | ||||
Colormap | 组件颜色或外貌改变时,TK忽略 | ||||
17 | Destroy | 组件被销毁时触发 | |||
下面来列举一下前缀:组合键修饰符
修饰符 | 说明 | |
Shift | Shift键被按下 | |
Control | Ctrl键被按下 | |
Alt | Alt键被按下 | |
Any | 任意一个键被按下 | |
Double | 2个事件在短时间内发生,如鼠标双击 | |
Triple | 3个事件在短时间内发生 | |
Lock | Caps Lock键被按下 |
表细节的后缀是否也可以一一举例呢?太多了,难以一一举例,鼠标3个键,键盘上按键就更多,所以,事件格式的后缀符号就不一一举例了,具体的事件由“前缀-事件-后缀”可以排列组合成很多事件,下面我把编程用得比较多的事件举例出来,到编程时大家肯定用得着。
鼠标事件 | 说明 | |
<Button-1> | 单击鼠标左键 | |
<Button-2> | 单击鼠标中键 | |
<Button-3> | 单击鼠标右键 | |
<Button-4> | 鼠标向上滚动 (Linux 系统用) | |
<Button-5> | 鼠标向下滚动(Linux 系统用) | |
<MouseWheel> | 鼠标滚动(windows 系统用) | |
<Motion> | 鼠标光标移动 | |
<B1-Motion> | 按下鼠标左键再拖曳,<Button1-Motion>的简写 | |
<B2-Motion> | 按下鼠标中键再拖曳移动 | |
<B3-Motion> | 按下鼠标右键再拖曳移动 | |
<ButtonRelease-1> | 释放鼠标左键 | |
<ButtonRelease-2> | 释放鼠标中键 | |
<ButtonRelease-3> | 释放鼠标右键 | |
<Double-Button-1> | 双击鼠标左键,可简写<Double-1> | |
<Double-Button-2> | 双击鼠标中键 | |
<Double-Button-2> | 双击鼠标右键 | |
<Enter> | 鼠标光标进入组件的范围内 | |
<Leave> | 鼠标光标离开组件的范围内 |
键盘事件 | 说明(事件多,大家要举一反三) | |
<FocusIn> | 组件得到输入焦点 | |
<FocusOut> | 组件失去输入焦点 | |
<Return> | 按下Enter键,键盘所有键都可被绑定 | |
<Key> | 按下某个键盘键 | |
<Ctrl-Up> | 按住Ctrl键时,再按下Up键 | |
<Alt-Up> | 按住Alt键时,再按下Up键 | |
<Shift-Up> | 按住Shift键时,再按下Up键 | |
<key-a> | 击键位a(小写状态下) | |
<key-A> | 击键位a(大写状态下) | |
<Double-Key-a> | 快速双击键位a | |
<Double-Key-A> | 快速双击键位a(大写状态下) | |
<Lock-Key-A> | 击键位a(大写状态下) | |
<Ctrl-Alt-a> | 按住Ctrl和Alt键 的同时,再击a键 | |
<Triple-a> | 快速连续3次击a键 |
组件事件 | 说明 | |
<Configure> | 组件大小和位置发生改变 |
用bind来绑定的事件调用的函数,我强调函数一定要写上event这个参数,这个参数很重要,这个参数是一个对象,这个对象的属性包含很多有用的信息。
Event事件对象的一些属性:
Event属性 | 说明 | |
.x .y | 相对于组件左上角的鼠标坐标位置 | |
.x_root .y_root | 相对于屏幕左上角的鼠标坐标位置 | |
.state | 辅助键(鼠标按键,ctrl,alt,shift,大写锁定键,NumLock键)的状态信息 | |
.keysym | 按键命名 | |
.keysym_num | 按键序号 | |
.keycode | 键码 | |
.time | 时间 | |
.type | 类型 | |
.widget | 组件 | |
char | 字符 | |
Width, height | 控件的新大小 | |
delta | Delta=120鼠标滚轮向上滚,=-120向下滚 | |
num | 鼠标的按键码,左中右键分别为1、2、3 |
不同的事件,event对象的属性是不一样的,比如有些属性就是键盘事件专属的,也有些是鼠标专属的。下面我用代码来说明。
下面在窗体创建一个标签,标签的鼠标单击事件绑定函数func
在函数里,分别输出event,以及event的各个属性值 。
from tkinter import * def func(event): print("event=",event) # 输出event print("event.widget=",event.widget) # 发生事件的组件 print("event.state=",event.state) # 辅助键信息 print("event.keysym=",event.keysym) # 命名按键 print("event.keysym_num=",event.keysym_num) # 按键序号 print("event.keycode=",event.keycode) # 键码 print("event.time=",event.time) # 时间 print("event.type=",event.type) # 类型 print("event.x=",event.x,' ',"event.y=",event.y) # 鼠标点击位置相对于组件左上角的坐标 print("event.x_root=",event.x_root,' ',"event.y_root=",event.y_root) # 鼠标点击位置相对于屏幕左上角的坐标 root=Tk() la1=Label(root ,bg='lightblue',width=30,height=5) la1.pack() la1.bind("<Button-1>",func) # 鼠标点击事件绑定func函数 root.mainloop()
运行后点击标签,输出:
event= <ButtonPress event num=1 x=130 y=69>
event.widget= .!label
event.state= 0
event.keysym= ??
event.keysym_num= ??
event.keycode= ??
event.time= 27015140
event.type= 4
event.x= 130 event.y= 69
event.x_root= 216 event.y_root= 178
分析:
以上有些输出是??,说明这个事件的event对象并没有这些属性,事实上,上面输出event属性=??的都是只支持键盘事件的。
我把上面的鼠标点击事件绑定函数代码,从
la1.bind("<Button-1>",func) # 鼠标点击事件绑定func函数
改成
la1.bind("<MouseWheel>",func) # 鼠标滚动事件绑定func函数
再测试一下,运行后,用鼠标滚轮向上滚动一下,输出:
event= <MouseWheel event delta=120 x=104 y=61>
……
向下滚动一下,输出:
event= <MouseWheel event delta=-120 x=104 y=61>
……
根据输出,我们发现,多了一个event属性参数delta,当它=120,是向上滚,当它=-120,是向下滚。
同时,还发现鼠标点击事件时,输出:event.type= 4,鼠标滚动时,输出 event.type= 38,这个属性参数,正好就是不同的事件类型代码。所以,我们根据event属性参数可以得到很多想要的信息。
小结:当对event事件不太熟悉,我们可以在绑定的函数里,用
print("event=",event) # 输出event
代码来了解一下更详细事件属性的情况。
下面用一个小程序让大家了解一个鼠标滚轮事件调整数值大小。
from tkinter import * def func(event): global a if event.delta==120: # 鼠标滚轮向前滚 a=a+1 # 数值加1 la1['text']=str(a) else:# 为-120,是鼠标滚轮向后滚 a=a-1 # 数值减1 la1['text']=str(a) root=Tk() a=0 la1=Label(root,text="0",bg='lightblue',width=30,height=5,font=('黑体',12,'bold')) la1.pack() la1.bind("<MouseWheel>",func) # 鼠标滚动事件绑定func函数 root.mainloop()
运行后,把鼠标移动到窗体的浅蓝界面上,滚动滚轮,会发现数值在变化。运行结果:
组件可以绑定相关事件,也可以取消,取消绑定事件语法很简单:
组件.unbind(”<事件>”)
例如:上面的代码已经有绑定代码:
la1.bind("<Button-1>",func) # 鼠标点击事件绑定func函数
那么,取消绑定代码就是
la1.unbind("<Button-1>") # 取消绑定
在创建组件时,有一个command参数可以调用函数,我们可以用匿名函数 lambda加入绑定回调函数的参数,(在按钮文章里,我有讲解),用bind方法,除了必须要加入的event这个参数,是否可以加入自己的参数?答案是可以的,这也要借用匿名函数lambda来帮忙。
command调用函数加入参数的语法是:
command=lambda: 函数(参数)
bind绑定函数加入参数的语法是:
组件.bind(事件,lambda event: 函数(event,参数)
下面用代码创建一个按钮,分别用2种方法调用函数并加入参数:
from tkinter import * def func1(cs): print("你好,",cs) def func2(evnet,cs): print("你好,",cs) root=Tk() but1=Button(root,text=" 确定 ",command=lambda:func1('张三')) but1.pack() but1.bind("<Button-1>",lambda event:func2(event,'李四')) # 加入参数 root.mainloop()
运行后,点击按钮,会输出:
你好,李四
你好,张三
各种事件是如此之多,以后的文章会用实例讲一下事件绑定的情况,以加强对相关知识的理解,下一篇文章我用实例“移动无标题栏窗体”来演示一下事件绑定具体运用。
以上文章是我的学习心得笔记,也算是为tkinter新手写的自学的教程,教程写完后,我会更多地写tkinter编程实例。
来源:济亨网
本文链接:http://wb98.com/post/315.html