Skip to content

事件处理

点击事件

当组件的点击事件(command)绑定某个函数(方法)时,按下组件时会自动调用该函数或方法。

python
import tkinter as tk

root = tk.Tk()
root.geometry("500x300+100+100")


# 定义功能函数
def button_command():
    print("你点击了按钮")


# 绑定事件
btn = tk.Button(root, text="确定", command=button_command)
btn.pack()

root.mainloop()

image-20201201152328412

绑定点击事件

python
import tkinter as tk

root = tk.Tk()
root.geometry("500x300+100+100")


# 定义功能函数
def button_command():
    print("你点击了按钮")


# # 绑定事件
# btn = tk.Button(root, text="确定", command=button_command)
# btn.pack()

# # 使用 config 配置方法配置参数
# btn = tk.Button(root, text="确定")
# btn.pack()
# btn.config(command=button_command)

# 使用对象的属性配置参数
btn = tk.Button(root, text="确定")
btn.pack()
btn['command'] = button_command

root.mainloop()

带参数的事件

python
import tkinter as tk

root = tk.Tk()


# 定义功能函数
def sum(a, b):
    print("%d + %d = %d" % (a, b, a + b))


def func():
    sum(1, 1)


# 绑定事件
# btn = tk.Button(root, text="确定", command=lambda: sum(1, 1))
btn = tk.Button(root, text="确定", command=func)

btn.pack()
root.geometry("300x300+200+200")

root.mainloop()

鼠标键盘事件

一个 tkinter 应用程序大部分时间花费在事件循环中(通过 mainloop()方法进入)。 事件可以有各种来源,包括用户触发的鼠标、键盘操作和窗口管理器触发的重绘事件(在多数情况下是由用户间接引起的)。

tkinter 提供一个强大的机制可以让你自由地处理事件,对于每个组件来说,可以通过 bind() 方法将函数或方法绑定到具体的事件上。当被触发的事件满足该组件绑定的事件时,tkinter 就会带着事件描述去调用 handler() 方法。

下面有几个例子,请随意感受下:

python
import tkinter as tk

root = tk.Tk()


def callback(event):
    print('点击位置', event.x, event.y)


frame = tk.Frame(root, width=200, height=200)
frame.bind("<Button-1>", callback)
frame.pack()

root.mainloop()

image-20200530023724251

在上面这个例子中,使用 Frame 组件的 bind() 方法将鼠标单击事件(<Button-1>)和自定义的 callback() 方法绑定起来。那么运行后的结果是——当你单击鼠标左键的时候,IDLE会相应地将鼠标的位置显示出来。

只有当组件获得焦点的时候才能接收键盘事件(Key),下面的例子中用focus_set()获得焦点,你可以设置 Frame 的 takefocus 选项为 True ,然后使用 Tab 将焦点转移上来。

python
import tkinter as tk

root = tk.Tk()


def callback(event):
    print('敲击位置', repr(event.char))


frame = tk.Frame(root, width=200, height=200)
frame.bind("<Key>", callback)
frame.focus_set()
frame.pack()

root.mainloop()

image-20200530023904855

最后一个例子展示捕获鼠标在组件上的运动轨迹,这里需要关注的是 <Motion> 事件:

python
import tkinter as tk

root = tk.Tk()


def callback(event):
    print('当前位置', event.x, event.y)


frame = tk.Frame(root, width=200, height=200)
frame.bind("<Motion>", callback)
frame.pack()

tk.mainloop()

image-20200530023957353

事件序列

Tkinter 使用一种称为事件序列的机制来允许用户定义事件,用户需使用 bind() 方法将具体的事件序列与自定义的方法绑定。事件序列是以字符串的形式表示的,可以表示一个或多个相关联的事件(如果是多个事件,那么对应的方法只有在满足所有事件的前提下才会被调用)。

事件序列使用以下语法描述:

<modifier-type-detail>

事件序列是包含在尖括号(<...>)中。

type 部分的内容是最重要的,它通常用于描述普通的事件类型,例如鼠标单击或键盘按键单击。

modifier 部分的内容是可选的,它通常用于描述组合键,例如 Ctrl+C、Shift+鼠标左键单击。

detail 部分的内容是可选的,它通常用于描述具体的按键,例如 Button-1 表示鼠标左键。比如:

(1)<Button-1> 表示用户单击鼠标左键。

(2)<KeyPress-H> 表示用户按下H键。

(3)Control-Shift-KeyPress-H 表示用户同时按下 Ctrl+Shift+H 键。

type

列举了 type 部分常用的关键词及含义。

modifier

列举了 modifier 部分常用的关键词及含义。

Event 对象

事件类型

事件类型<Button-1>:鼠标点击,1代表左键,2代表中键,3代表右键。

<B1-Motion>:鼠标拖动。

<ButtonRelease-1>:鼠标点击释放。

<Double-Button-1>:双击鼠标。

<Enter><Leave>:鼠标进入、离开控件。

<Key>:键盘点击。

<KeyPress-A> :键盘点击某个按键。A可以替换称对应的按键名称。

<Control-A>:Ctrl+A。同理,Control可以替换称Alt、Shift等。

<Control-Shift-H>:三个按键事件。

<KeyRelease-A>:键盘释放。

<Configure>:当控件的位置或大小改变时触发。

<Activate><Deactivate>:控件激活。

<Destroy>:控件被销毁。

<FocusIn><FocusOut>:控件获得焦点。

<Visibility>:控件可见。

<Shift_L> 左shift按键响应

<Shift_R> 右shift按键响应

<F2> F2按键相应,F3,F4.....

<Return> 回车按键相应

<BackSpace> 退格删除键相应

事件对象:event。

python
type = event.type  # 事件类型  
widget = event.widget  # 触发事件的控件  
x, y = event.x, event.y  # 触发位置  
char = event.char  # 键盘事件内容  
num = event.num  # 鼠标事件内容  
width, height = event.width, event.height  # 控件新大小

当 tkinter 去回调预先定义的函数时,将带着 Event 对象(作为参数)去调用

Event 对象的属性及含义

属 性含 义
widget产生该事件的组件
x,y当前的鼠标位置坐标(相对于窗口左上角,像素为单位)
x_root, y_root当前的鼠标位置坐标(相对于屏幕左上角,像素为单位)
char按键对位的字符(键盘专属事件)
keysym名,见下方 Key names(键盘专属事件)
keycode按键名,见下方 Key names(键盘专属事件)
num按键数字(鼠标专属事件)
width, height组件的新尺寸(Configure 事件专属)
type该事件类型

当事件为 <Key><KeyPress><KeyRelease> 的时候,detail可以通过设定具体的按键名(keysym)来筛选。例如 <Key-H> 表示按下键盘上的大写字母H时候触发事件,<Key-Tab>表示按下键盘上的Tab按键的时候触发事件。

下面列举了键盘所有特殊按键的 keysym 和 keycode(其中的按键码是对应美国标准 101 键盘的 Latin-1 字符集,键盘标准不同对应的按键码不同,但按键名是一样的)。

获取键码值

python
# encoding: utf-8

from tkinter import *


# 处理鼠标事件,me为控件传递过来的鼠标事件对象
def processMouseEvent(me):
    print("me=", type(me))  # me= <class>

    print("位于屏幕", me.x_root, me.y_root)
    print("位于窗口", me.x, me.y)
    print("位于窗口", me.num)


# 处理鼠标事件,ke为控件传递过来的键盘事件对象
def processKeyboardEvent(ke):
    print("ke.keysym", ke.keysym)  # 按键别名
    print("ke.char", ke.char)  # 按键对应的字符
    print("ke.keycode", ke.keycode)  # 按键的唯一代码,用于判断按下的是哪个键</class></key></button-1>


window = Tk()
window.title("鼠标键盘事件")

# 打包一个白色画布到窗口
canvas = Canvas(window, width=200, height=200, bg="white")
canvas.focus_set()  # 让画布获得焦点,对于键盘
canvas.pack()

# 绑定鼠标左键事件,交由 processMouseEvent 函数去处理,事件对象会作为参数传递给该函数
canvas.bind(sequence="<Button-1>", func=processMouseEvent)

# 绑定鼠标键盘事件,交由 processKeyboardEvent 函数去处理,事件对象会作为参数传递给该函数
canvas.bind(sequence="<Key>", func=processKeyboardEvent)

# 消息循环
window.mainloop()