Tkinter事件处理

Tkinter应用会花费大部分的时间在处理事件循环中(通过mainloop()方法进入),事件可以是触发的鼠标,键盘的操作,管理窗口触发的重绘事件(在多数情况下都是有用户间接引起的)。

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

 from tkinter import *

 root = Tk()
def callbach(event):
print("点击位置:",event.x,event.y)
frame = Frame(root,width=,height=)
frame.bind("<Button-1>",callbach)
frame.pack()
mainloop()

执行结果:

在例子中,使用Frame组件的bind()方法将鼠标的单击事件和自定义的callbach()方法绑定起来,那么运行的结果就是:当鼠标点击的时候,IDLE会相应的将鼠标的位置显示出来。

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

 from tkinter import *

 root = Tk()
def callbach(event):
print("点击位置:",event.x,event.y)
frame = Frame(root,width=,height=)
frame.bind("<Key>",callbach)
frame.focus_set()
frame.pack()
mainloop()

执行结果:

在来实现一个展示捕获鼠标轨迹的组件,需要关注的是事件。

 from tkinter import *

 root = Tk()
def callbach(event):
print("点击位置:",event.x,event.y)
frame = Frame(root,width=,height=)
frame.bind("<Motion>",callbach)
frame.pack()
mainloop()

执行结果:

事件序列

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

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

<modifier-type-detail>

修饰 部分为可选内容,一般在组合事件中用于多功能按键组合的描述。如:Ctrl + Shift + V;

类型 部分用于描述一般的事件对象类型,如键盘按键或鼠标动作等;

type区域是事件说明符中最重要的部分,它说明我们想绑定哪一类的事件

例如Button\Key或者如进入、配置之类的窗口管理事件。

详细描述 部分为可选内容,一般用于描述事件具体单元对象,如KeyPress-A,表示按键盘A键

Modifier和detail区域用于额外的信息

在许多情况下可以省略,还有各种方法来简化事件字符串,例如为了匹配键盘键,您可以省略

尖括号,只需使用键,当然要包含在尖括号内让我们来看看最常见的事件格式

事件格式

<Button-1>鼠标左键按下事件,1表示左键;2-鼠标中键;3-鼠标右键

当您在组件上按下鼠标左键,随后的鼠标事件(移动、释放)就会发送到当前组件,即使

鼠标移动到当前组件之外,鼠标指针的的当前位置在传递给回调函数的event对象的x,y中

<Button-1>、<ButtonPress-1>、<1>都是同义词

<B1-Motion>按住鼠标左键移动鼠标,鼠标指针的当前位置在传递给回调函数的event中的x\y提供

<ButtonRelease-1>鼠标左键被释放

<Double-Button-1>鼠标左键被双击,你可以用Double表示双击,还可以用Triple表示三击

注意,如果你绑定了<Button-1>和<Double-Button-1>,那么2个事件都被触发

键入部分常用的关键字及含义

事件类型

意义描述

Activate

组件状态变化事件,未激活变为激活时触发;

与 Deactivate 相对

Button

鼠标按键点击事件;

由描述部分指定具体按键:

  <Button-1> 鼠标左键

  <Button-2> 鼠标中键

  <Button-3> 鼠标右键

  <Button-4> 滚轮上(linux)

  <Button-5> 滚轮下(linux)

ButtonRelease

释放鼠标按键事件。强调释放动作

Configure

组件尺寸改变事件

Deactivate

组件状态改变事件。激活变为未激活;

与 Activate 相对

Destroy

组件被销毁触发事件

Enter

鼠标指针进入组件区域事件;

与 Leave 相对

Expose

窗口或组件的部分被显示时触发事件,比如某部分被置顶

FocusIn

获得焦点事件。如果组件的takefocus属性为True,则用户可通过Tab按键切换组件焦点。也可用focus_set()方法设置组件焦点

FocusOut

失去焦点事件

KeyPress

键盘按键事件。强调按下动作;

由描述部分指定具体按键,如 <KeyPress-A>、<KeyPress-B>;

可简写为Key

KeyRelease

释放键盘按键事件。强调释放动作

Leave

鼠标指针离开组件区域事件;

与 Enter 相对

Map

组件被映射时触发事件。指在程序中,该组件被调用(组件显示、隐藏等)。如调用grid()方法

Motion

鼠标在组件区域内移动事件

MouseWheel

鼠标滚轮事件。该事件序列支持Windows和Mac 等同于Linux下的Button-4/5

Unmap

组件被取消映射事件;

与Map相对

Visibility

应用程序至少有一部分被置顶(即被显示出来)事件

<Shift-Up>

用户按下shift键同时按下向上键触发,也可以用Alt,shift,control

frame1.bind("<Shift M>",shiftm) 当同时按下shift 和m 后回调函数shiftm

<Return>

用户按下回车键,你可以绑定键盘上几乎所有键,Shift_L(左边的shift键)

Delete\F1\F5\Num_Lock都可以

修饰语

修饰符

意义

Alt

按下Alt键

Any

按下任意键。如<Any-KeyPress>,表示按下任意键事件

Control

按下Ctrl键

Double

被修饰的事件类型连续两次触发。如<Double-Button-1>,表示双击鼠标左键

Lock

大写字母锁定键

Shift

按下Shift

Triple

被修饰的事件类型连续三次触发

事件对象

当Tkinter回调预定义的函数时,将带着事件对象(作为参数)去掉用。

事件对象的属性及含义

属性

意义描述

widget

产生事件的组件

x,y

以窗口左上角为原点,鼠标指针的坐标。以像素为单位

x_root,y_root

以屏幕左上角为原点,鼠标指针的坐标,以像素为单位

char

键盘按键字符

keysym

键盘按键名

keycode

键盘按键码

num

鼠标按钮数字

width,height

组件尺寸改变后的宽和高

type

事件类型

当事件为,,的时候,细节可以通过设定具体的按键名来筛选,例如表示按下键盘的大写字母H的时候触发事件,表示按下键盘上的Tab键的时候触发事件。

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

键盘所有特殊按键的键符和键码

按键名(keysym)

按键码(keycode)

按键描述

Alt_L

64

左Alt

Alt_R

113

右Alt

BackSpace

22

退格

Cancel

110

break键

Caps_Lock

66

大写字母锁定

Control_L

37

左Ctrl

Control_R

109

右Ctrl

Shift_L

50

左Shift

Shift_R

62

右Shift

Insert

106

插入键

Delete

107

删除键

Left

100

左方向键

Right

102

右方向键

Up

98

上方向键

Down

104

下方向键

Home

97

Home键

End

103

End键

Escape

9

Esc键

Execute

111

Sysreq键

F1~F11

67~77

F1键到F11键(一一对应)

F12

96

F12键

Linefeed

54

Linefeed键(Ctrl + J)

KP_0

90

数字键盘0

KP_1

87

数字键盘1

KP_2

88

数字键盘2

KP_3

89

数字键盘3

KP_4

83

数字键盘4

KP_5

84

数字键盘5

KP_6

85

数字键盘6

KP_7

79

数字键盘7

KP_8

80

数字键盘8

KP_9

81

数字键盘9

KP_Subtract

82

数字键盘 -

KP_Add

86

数字键盘 +

KP_Begin

84

数字键盘中间键(5)

KP_Decimal

91

数字键盘点键

KP_Delete

91

数字键盘删除

KP_Divide

112

数字键盘反斜杠 /

KP_Up

80

数字键盘上方向

KP_Left

83

数字键盘左方向

KP_Right

85

数字键盘右方向

KP_Down

88

数字键盘下方向键

KP_End

87

数字键盘End键

KP_Enter

108

数字键盘回车

KP_Home

79

数字键盘Home

KP_Insert

90

数字键盘插入

KP_Multiply

63

数字键盘星号 *

KP_Next

89

数字键盘PageDown

KP_Prior

81

数字键盘PageUp

Next

105

PageDown键

Num_Lock

77

数字键盘锁定

Pause

110

Pause暂停

Print

111

屏幕打印

Prior

99

PageUp键

Return

36

回车

Scroll_Lock

78

ScrollLock键

Tab

23

制表按键

按键名(keysym)

按键码(keycode)

按键描述

Alt_L

64

左Alt

Alt_R

113

右Alt

BackSpace

22

退格

Cancel

110

break键

Caps_Lock

66

大写字母锁定

Control_L

37

左Ctrl

Control_R

109

右Ctrl

Shift_L

50

左Shift

Shift_R

62

右Shift

实例和类的绑定

以上的例子中我们用的都是在实例上使用bind方法,这意味着这样只能bind在一个组件上,

如果我们创建一个新的组件,他们不会继承这些绑定关系。

不过Tkinter也提供了类级别和应用级别的bind,实际上,你可以使用以下级别的binding

1.组件实例

2.组件的顶层窗体(Toplevel 或者 root)

3.组件类,用bind_class方法

4.整个应用,用bind_all方法

比如,你可以用bind_all来绑定F1按钮的点击,这样你能在这个应用的如何地方点击都可以弹出帮助框

但如果同一个键你在多处绑定了怎么办?

首先,在以上4个层次之内,Tkinter选择最接近匹配的方式。比如为<Key>

和<Return>事件创建实例绑定,那么只有按下Enter键之后才会调用<Return>的回调函数

但是,如果你如果在以上4个层次间,比如你同时向toplevel组件添加<Return>绑定,那么将调用2个绑定

Tkinter首先调用实例级别的最佳绑定,最后在应用程序级别调用最佳可用绑定,因此,

在极端情况下,单个事件可以调用4个事件处理程序。

常见的混乱原因是当您尝试使用绑定来覆盖标准组件的默认行为。例如,假设你想在

文本框内禁止输入回车键,这样用户就无法输入多行数据,也行你会用下面的小伎俩

 def ignore(event):
pass text.bind("<Return>",ignore)

或者,你喜欢一行的简洁代码

text.bind("<Return>",lamdba e:None)

不幸的是,新的一行依然会插入,因为,以上的绑定仅仅应用在应用级别,

而标准的行为依然有类级别的绑定实现了。

你可以使用bind_class方法来改变类级别的绑定,但这将更改应用程序中所有文本组件的行为。下面是比较合理的解决办法

 def ignore(event):
return "break"
text.bind("<Return>", ignore)

顺便说一句,如果你真的想改变所有文本组件的默认行为,你可以用以下bind_class方法

top.bind_class("Text", "<Return>", lambda e: None)

真的不建议这么做,不要改变组件的默认行为。

协议

除了事件绑定,Tkinter还提供了协议处理的机制,这里的协议指的是应用程序和windows manager之间的互动

最常见的是WM_DELETE_WINDOW,用于定义当用户使用窗口管理器显式关闭窗口是的事件。

你可以用protocol方法来安装这个协议的回调函数(这个组件必须是root或者Toplevel组件)

widget.protocol("WM_DELETE_WINDOW", handler)

一旦你注册了自己的处理函数,Tkinter将不再自动的关闭程序,比如下面这个例子

from Tkinter import *
import tkMessageBox def callback():
if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"):
root.destroy() root = Tk()
root.protocol("WM_DELETE_WINDOW", callback)
root.mainloop()

注意,即使你没有在顶层窗口注册WM_DELETE_WINDOW的处理程序,窗口还是会被销毁的。最好还是自己注册一个处理程序

top = Toplevel(...)#确保窗口小部件实例被删除
top.protocol(“WM_DELETE_WINDOW”,top.destroy)

GUI的最终选择 Tkinter(九):事件的更多相关文章

  1. Python之GUI的最终选择(Tkinter)

    首先,Tkinter是Python默认的GUI库,想IDLE就是用Tkinter设计出来的,因此直接导入Tkinter模块就可以啦 1 import tkinter (1)Tkinter初体验: 1 ...

  2. GUI的最终选择Tkinter模块初级篇

    一.Tkinter模块的基本使用 1)实例化窗口程序 import tkinter as tk app = tk.Tk() app.title("FishC Demo") app. ...

  3. GUI的最终选择 Tkinter(五):Text用法

    Text组件 绘制单行文本使用Label组件,多行选使用Listbox,输入框使用Entry,按钮使用Button组件,还有Radiobutton和Checkbutton组件用于提供单选或多选的情况, ...

  4. GUI的最终选择 Tkinter(一):Tkinter最初体验

    EasyGui就是一个简单的文字交互界面模块,从今天开始来开始学习Tkinter Tkinter是Python标准的Gui库,它实际是建立在Tk技术上的,Tk最初是为Tcl(一门工具名语言)所涉及的, ...

  5. GUI的最终选择 Tkinter(七):菜单Menu组件、Menubutton组件、OptionMenu组件

    Menu组件 今天说的Menu组件就是一些菜单组件,开始点点点... Tkinter提供了一个Menu组件,可以实现顶级菜单,下拉菜单和弹出菜单.由于底层是代码实现和优化的,所以不太建议通过按钮和其他 ...

  6. GUI的最终选择 Tkinter(四):Entry、Listbox、Scrollbar和Scale组件

    Entry组件 Entry组件就是平时所说的输入框.输入框是程序员用到的最多的一个程序,例如在输入账号和密码的时候需要提供两个输入框,用于接收密码的输入框还会有星号将实际输入的内容隐藏起来. Tkin ...

  7. GUI的最终选择 Tkinter(三):Checkbutton组件和Radiobutton组件、LabelFrame组件

    Checkbutton组件 Checkbutton组件就是常见的多选按钮,而Radiobutton则是单选按钮 from tkinter import * root = Tk() v = IntVar ...

  8. GUI的最终选择 Tkinter(六):Canvas组件

    Canvas组件,是一个可以让你任性的组件,一个可以让你随心所欲地绘制界面的组件.Canvas是一个通用的组件,它通常用于显示和编辑图形,可以用它来绘制直线,圆形,多边形,甚至是绘制其他组件. 在Ca ...

  9. GUI的最终选择Tkinter模块练习篇

    一.Canvas画布练习 1)简单的绘制图框 from tkinter import * # 构建一个窗口 tk = Tk() # 画布 canvas= Canvas(tk,width=,height ...

随机推荐

  1. unity3d mvvm c#

    using UnityEngine; using System.Collections; public interface IState { void BeforEnter(); void Befor ...

  2. codeforces 658D D. Bear and Polynomials(数学)

    题目链接: D. Bear and Polynomials time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  3. 取分组TOPN好理解案例

  4. MySQL学习_查看各仓库产品的销售情况_20161102

    订单表结构是具体到每个订单下面多个产品,而仓库出货的表结构是对每个订单的金额汇总 不区分订单产品 因此如果想计算每个仓库每个产品的销售情况 需要将两个表连接起来 并且产品是昨天在线且有库存的产品 #昨 ...

  5. 「USACO08DEC」「LuoguP2922」秘密消息Secret Message(AC自动机

    题目描述 Bessie is leading the cows in an attempt to escape! To do this, the cows are sending secret bin ...

  6. bzoj 1731 [Usaco2005 dec]Layout 排队布局——差分约束

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1731 对差分约束理解更深.还发现美妙博客:http://www.cppblog.com/me ...

  7. Redis使用的相关问题

    Redis用那些数据结构? 字符串类型String 字典Hash 列表List 集合Set 有序集合SortedSet HyperLogLog.Geo.Pub/Sub Redis Module.Blo ...

  8. JS判断上传文件类型

    /*   * 判断图片类型   */    function checkImgType(ths){        if (ths.value == "") {            ...

  9. Guid string 转换

    System.Guid.NewGuid().ToString(); //GUID带-分割// db1b98e9-6f93-41aa-84f8-5eb773e93d67System.Guid.NewGu ...

  10. 大白话5分钟带你走进人工智能-第二十六节决策树系列之Cart回归树及其参数(5)

                                                    第二十六节决策树系列之Cart回归树及其参数(5) 上一节我们讲了不同的决策树对应的计算纯度的计算方法, ...