Python 的Tkinter包系列之五:事件

Python Tkinter包系列之五:事件

事件处理(Event Handling),是 GUI 程序中不可或缺的重要组成部分,相比来说,控件只是组成一台机器的零部件, 而事件处理则是驱动这台机器“正常”运转的关键所在,是实现人机交互的关键。

在一款 GUI 程序中,我们将用户对软件的操作统称为“事件”,比如鼠标点击按钮、键盘输入文本以及窗口管理器触发的重绘等,这些事件有一个共同的特点,即都是由用户自身直接或者间接触发的。

一个 GUI 应用整个生命周期都处在一个消息循环 (event loop) 中,它等待事件的发生,并作出相应的处理。 Tkinter 提供了用以处理相关事件的机制处理函数可被绑定给各个控件的各种事件。

事件(event)是应用程序需要知道识别的一些事情。或者说,事件(event)表示程序某件事发生的信号,可以用来触发一段特定的代码——事件处理程序。

事件处理程序(event handler)是应用程序中的一个函数,当事件发生时调用它。

当事件发生在控件(widget:组件、小部件、控件)上,调用事件处理程序时,我们称之为绑定( binding)。绑定就是将事件和事件处理程序建立联系。

Tkinter如何指定事件处理程序

一、在创建控件对象时,可以使用控件中的command参数指定事件处理程序:command=函数,那么点击控件的时候将会触发函数。详情可参见Python 的Tkinter包系列之一:窗口初步_软件开发技术爱好者的博客-CSDN博客 有关部分。

二、还可以使用绑定(binding)方法指定事件处理程序,Tkinter可以在以下三个级别将事件处理程序绑定(binding)到事件:

1)实例绑定(Instance binding):可以将事件绑定到一个特定的控件。

tkinter —— Tcl/Tk 的 Python 接口 — Python 3.10.8 文档

54.1. Levels of binding

其语法格式如下:

widget.bind(sequence,func,add='')

其中,widget 代表控件的控件对象,之后,采用 bind() 方法进行事件绑定,该函数的参数:

sequence:表示事件的类型,也称事件码,是 Tkinter 模块规定好的,并使用“尖括号”的形式进行包裹;Tkinter 中经常使用的事件类型,描述格式为:<[modifier-]-type[-detail]>,其中:

modifier:事件修饰符。如:Alt、Shit组合键和Double事件。

type:事件类型。如:按键(Key)、鼠标(Button/Motion/Enter/Leave/Relase)、Configure等。

detail:事件细节。如:鼠标左键(1)、鼠标中键(2)、鼠标右键(3)。

具体见下图(注意大小写!):

 【注:也可以使用短表达方式,如:
'1' 同 '<Button-1>'
'A' 同 '<KeyPress-A>' (不适用空白键及'<')】

func:表示事件的处理函数,当触发事件时执行。事件处理函数或为普通的函数,或为类中定义的函数(也叫方法)。

函数

def 事件处理函数名称(event):

     函数体

类的一个方法

def 事件处理函数名称(self, event):

     函数体

其中,self代表实例本身

使用绑定(binding)方法指定事件处理程序函数,和前介绍的面通过command参数指定事件处理函数不同之处是有一个参数,一般写为event,也可以用其它自定义名称(因损害易读性不建议),通过这个参数能够获取到Event对象的属性(attributes)。

传递给处理程序的Event对象的常用属性如下:

【详见54.6. Writing your handler: The Event class

【在tkinter中,event是一个类,当某个事件发生时,生成一个event对象,不同类型的事件生成具有不同属性的event对象。一个具体事件如<Button-1>是事件类(event class)的一个实例——event对象,事件类中设定了众多属性,其中部分属性是通用的,另一部分属性属于特定事件类型的。】

add:是可选参数,默认为'',表示本次绑定的函数将替换与此事件关联的其他所有绑定函数;'+'表示将函数添加到绑定到此事件类型的函数列表中。

2)类绑定(Class binding):可以将事件绑定到类的所有小部件。其语法格式如下:

widget.bind_class(className, sequence,func,add='')

其中,className 代表一类控件的字符串;widget 代表控件对象,sequence、func、add见前面说明。

.bind_class类似于.bind(),但适用于所有名为className的控件(例如,“Button”)。

3)应用程序绑定(Application binding),也叫为所有控件绑定:为所有组件绑定一个操作(所有操作都会当作对主界面的操作)。其语法格式如下:

widget.bind_all(sequence,func,add='')

其中,widget 代表控件对象, sequence、func、add见前面说明。

bind_all类似于.bind(),但适用于整个应用程序中的所有控件——若用bind_all方法绑定窗口里面的一个控件,那么整个窗口的控件都被绑定。

若用bind_all方法绑定窗口里面的一个控件,那么整个窗口的控件都被绑定。

使用bind方法绑定(实例绑定)事件示例的源码:


import tkinter 

root=tkinter.Tk()
root.title("bind方法绑定(实例绑定)事件")
root.geometry('450x350+300+200')

# 定义事件处理函数
def show_key(event):
    # 查看触发事件的按钮
    s=event.keysym
    # 将其显示在按钮控件上
    lb.config(text=s)

# 添加一个按钮控件
lb=tkinter.Label(root,text='请按键试试,在此将显示你的按键情况',width=30,fg='blue',font=('微软雅黑',15))
# 给按钮控件绑定事件,按下任意键,然后调用事件处理函数。注意,此处需要在英文状态下进行按键
lb.bind('<Key>',show_key) #使用bind方法绑定(实例绑定)事件
lb.focus_set() # 设置获取焦点, Label 控件获取焦点后才能接收键盘事件
lb.pack()

# 显示窗口
root.mainloop()

程序运行效果:

请在英文状态下进行按键试试看。

使用bind_class方法绑定(类绑定)事件示例的源码:

import tkinter

# 创建主窗口
root = tkinter.Tk()
root.title("bind_class方法绑定(类绑定)事件示例")
root.geometry('450x350+300+200')
 
# 按钮1
btn1 = tkinter.Button(root,text = '1')
btn1.place(x = 20,y = 20,width = 40,height = 40)
# 按钮2
btn2 = tkinter.Button(root,text = '2')
btn2.place(x = 80,y = 20,width = 40,height = 40)
# 按钮3
btn3 = tkinter.Button(root,text = '3')
btn3.place(x = 140,y = 20,width = 40,height = 40)
# 按钮4
btn4 = tkinter.Button(root,text = '4')
btn4.place(x = 20,y = 80,width = 40,height = 40)
# 按钮5
btn5 = tkinter.Button(root,text = '5')
btn5.place(x = 80,y = 80,width = 40,height = 40)
# 按钮6
btn6 = tkinter.Button(root,text = '6')
btn6.place(x = 140,y = 80,width = 40,height = 40)
 
def changebg(event):
    # 鼠标移到按钮上按钮变红
    event.widget['bg'] = 'red'
def changebg1(event):
    # 鼠标离开按钮上按钮变白
    event.widget['bg'] = 'white'
# 绑定按钮鼠标进入事件
btn1.bind_class('Button','<Enter>',changebg)
btn1.bind_class('Button','<Leave>',changebg1)
 
# 加入消息循环
root.mainloop()

程序运行效果:

鼠标移到按钮上按钮变红,鼠标离开按钮上按钮变白。

使用bind_all方法绑定(应用程序绑定)事件示例的源码:

import tkinter
 
# 创建主窗口
root = tkinter.Tk()
root.title("bind_all方法绑定事件示例")
root.geometry('450x350+300+200')
 
# 按钮
btn1 = tkinter.Button(root,text = '按钮')
btn1.pack()
# 输入框
entry = tkinter.Entry(root)
entry.pack()
# 多行输入框
text = tkinter.Text(root,width = 30,height = 5)
text.pack()
# 函数
def changeentry(event):
    # 鼠标点击任意控件包括窗体,Entry输入框都会变红
    entry['bg'] = 'red'
 
# 事件绑定
btn1.bind_all('<Button-1>',changeentry)
 
# 加入消息循环
root.mainloop()

程序运行效果:

鼠标点击任意控件包括窗体,Entry输入框都会变红。

event作为事件处理函数的参数,传入的参数为一个 Event 实例——就是绑定事件的控件。将event作为事件处理函数的参数,通过它可以访问由此传入对象的属性。

下面给出event作为事件处理函数的参数的示例源码:

import tkinter 
win =tkinter.Tk()
win.title("event作为事件处理函数的参数示例")
win.geometry('400x300')

#event作为事件处理函数的参数,可以获取到控件(widget)对象
def fun(event):
    #显示鼠标点击位置
    print('相对Frame控件左上角位置:',event.x,event.y)
    print('点击屏幕位置:',event.x_root,event.y_root)

#将Frame控件加入到窗口中
frame =tkinter.Frame(win,width = 300,height = 200,background ="Light green")
frame.bind('<Button-1>',fun) #将Frame控件和鼠标左键单击事件绑定
frame.focus_set()
frame.pack()

win.mainloop()

程序运行效果:

鼠标点击窗体Frame控件——已经将其背景设置为Light green(浅绿色)区域——试试看。

通常,一个事件绑定方法绑定一个事件处理程序,若想绑定多个事件处理程序,在绑定方法中使用参数add="+"。

使用参数add="+"将函数添加到绑定到此事件类型的函数列表中­示例源码:

import tkinter

#事件处理程序1
def show1(event):
    print("来自show1")

#事件处理程序2
def show2(event):
    print("来自show2")

#事件处理程序3
def show3(event):
    print("来自show3")
    
#事件处理程序4
def show4(event):
    print("来自show4")

#事件处理程序4
def show5(event):
    print("来自show5")

root = tkinter.Tk()
root.geometry('300x200')
root.title("使用参数add示例")
btn = tkinter.Button(root, text="Click")
btn.pack()
btn.bind("<Button-1>", show1)
btn.bind("<Button-1>", show2)
btn.bind("<Button-1>", show3)
btn.bind("<Button-1>", show4, add="+")
btn.bind("<Button-1>", show5, add="+")

root.mainloop()

程序运行效果:

点击“Click”按钮,在 “Python Shell”窗口中显示:

来自show3
来自show4
来自show5

本例解释了add参数,若为''表示本次绑定的函数将替换与此事件关联的其他所有绑定函数,默认为'';'+'表示将函数添加到绑定到此事件类型的函数列表中。

OK!

参考

Tkinter 8.5 reference: a GUI for Python (tkdocs.com)  54

python - [译][Tkinter 教程15] event 事件绑定_个人文章 - SegmentFault 思否

python学习笔记:tkinter之事件(event)、事件处理(event handler)、事件绑定(event binding)、基于事件的动画(animation)_xiaozhimonica的博客-CSDN博客_tkinter animation

  • 8
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值