当前位置:首页 » tkinter » 正文

tkinter的事件绑定详解-何老师

为标签增加响应鼠标点击事件的功能

我们做的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方法绑定的函数有优先调用权。

  我们再用鼠标右键双击按钮,会输出“我被双击了”,可见,按钮因此增加了对鼠标双击反应的能力。同样道理,我们还可以为按钮或其它组件增加鼠标右键单击,双击事件反应功能,鼠标移动事件反应功能,键盘事件反应功能…………

事件绑定语句中的add参数

上面的代码,我们已经用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事件分类及语法

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()

  运行后,把鼠标移动到窗体的浅蓝界面上,滚动滚轮,会发现数值在变化。运行结果:

                                              1.PNG

取消事件绑定

组件可以绑定相关事件,也可以取消,取消绑定事件语法很简单:

组件.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://wb86.com/post/315.html

    << 上一篇 下一篇 >>

    湘公网安备 43011102000514号 - 湘ICP备08100508号