Python之tkinter 事件和绑定

事件绑定的基本简介

  其实GUI程序是一种事件导向的应用程序设计,事件的来源可能是用户单击鼠标、键盘输入或是Widget 状态改变。tkinter提供一些机制让我们可以针对这些事件做更进一步的处理,这些处理的方式称为事件处理程序

Widget 的 command 参数

例子:复习

import tkinter

def show():
    label.config(text="Click")

def oneVar():
    if varOne.get():
        label.config(text="One!!!")
    else:
        label.config(text="One")

def twoVar():
    if varTwo.get():
        label.config(text="Two!!!")
    else:
        label.config(text="Two")

root = tkinter.Tk()
root.geometry("300x200")

btu = tkinter.Button(root, text="Click", command=show)
btu.pack(anchor=tkinter.W)

varOne = tkinter.BooleanVar()
cbnOne = tkinter.Checkbutton(root, text="One", variable=varOne, command=oneVar)
cbnOne.pack(anchor=tkinter.W)

varTwo = tkinter.BooleanVar()
cbnTwo = tkinter.Checkbutton(root, text="Two", variable=varTwo, command=twoVar)
cbnTwo.pack(anchor=tkinter.W)


label = tkinter.Label(root, bg="lightgreen", fg="red", height=2, width=12, font="Times 16 bold")
label.pack()

root.mainloop()

运行结果:
在这里插入图片描述
我们通过command=show,来设计show函数,这个show函数就是事件处理程序

事件绑定

语法格式如下

widget.bind(event, handler)

参数:

  • widget:事件的来源,可以是root窗口对象,或是任意的Widget控件,例如,功能按钮,选项按钮,复选框等等
  • 第一个参数:evevt,事件的参数,下面具体说明
  • 第二个参数:handler,事件处理程序,也就是根据event来触发的函数

下面我们来看具体参数

鼠标相关的事件参数
鼠标事件 说明
<Button-1> 鼠标左键单击
<Button-2> 鼠标中键单击
<Button-3> 鼠标右键单击
<Button-4> 鼠标滑轮向上滚动(Linux)
<Button-5> 鼠标滑轮向下滚动(Linux)
<B1-Motion> 鼠标左键拖动
<B2-Motion> 鼠标中键拖动
<B3-Motion> 鼠标右键拖动
<ButtonRelease-1> 鼠标左键释放
<ButtonRelease-2> 鼠标中键释放
<ButtonRelease-3> 鼠标右键释放
<Double-Button-1> 鼠标左键双击
<Double-Button-2> 鼠标中键双击
<Double-Button-3> 鼠标右键双击
<Enter> 鼠标指针进入控件
<Leave> 鼠标指针离开控件

  上述的参数,执行后鼠标光标相对控件的位置会被存入事件对象的x和y变量中,所以这就是为什么我们在handler函数中要加入event形参,这个是必须要传的

注:

<1> = <Button-1> =<ButtonPress-1>
<2> = <Button-2> = <ButtonPress-2>
<3> = <Button-3> =<ButtonPress-3>

这是通用的,<>不能省略

绑定的方式

button.bind("<Button-1>", handler)
鼠标绑定的基本应用

例子:鼠标移动,右下方看到鼠标目前的座标

import tkinter

def moving(event):
    # .x_root, .y_root是相对于整个屏幕
    # 获取x轴座标(相对于窗口)
    x = event.x
    # 获取y轴座标(相对于窗口)
    y = event.y
    textvar = "座标 : x:%r  y:%r" % (x, y)
    var.set(textvar)

root = tkinter.Tk()
root.geometry("300x200")
x, y = 0, 0
var = tkinter.StringVar()
text = "座标 : x:%r  y:%r" % (x, y)
var.set(text)

label = tkinter.Label(root, textvariable=var)
label.pack(anchor=tkinter.S, side=tkinter.RIGHT, padx=10, pady=10)

# 事件是鼠标移动,执行moving函数
root.bind("<Motion>", moving)

root.mainloop()

运行结果:

在这里插入图片描述
moving(event)中的event是可以自定义的,但是不能没有

键盘相关的事件参数
键盘事件 说明
<Return> 回车
<Cancel> Break键
<BackSpace> BackSpace键
<Tab> Tab键
<Shift_L> 左Shift键
<Alt_L> 左Alt键
<Control_L> 左Control键
<Shift_R> 右Shift键
<Alt_R> 右Alt键
<Control_R> 右Control键
<Pause> Pause键
<Caps_Lock> Caps_Lock键
<Escape> Escapel键,俗称Esc
<Prior> PageUp键
<Next> PageDown键
<End> End键
<Home> Home键
<Left> 左箭头
<Up> 上箭头
<Right> 右箭头
<Down> 下箭头
<Print> Print Screen
<Insert> Insert键
<Delete> Delete键
<F1> F1键
<F2> F2键
<F3> F3键
<F4> F4键
<F5> F5键
<F6> F6键
<F7> F7键
<F8> F8键
<F9> F9键
<F10> F10键
<F11> F11键
<F12> F12键
<Num_Lock> Num_Lock键
<Scroll_Lock> Scroll_Lock键
<plus> 小键盘上的 + 键
<minus> 小键盘上的 - 键
<asterisk> 小键盘上的 * 键
<slash> 小键盘上的 / 键
<key> 任意键

注:

<key> = <KeyPress> = <KeyRelease>
键盘绑定的基本应用

例子:当我们按下Tab时,tkinter做出响应

import tkinter

def tab(event):
	# keysym 键盘事件对应的字符串
    print(f"按下了{event.keysym}键")

root = tkinter.Tk()
root.geometry("100x80")
root.bind("<Tab>", tab)

root.mainloop()

运行结果:
在这里插入图片描述

可打印的字符
字符 说明
<a> 字母a
<b> 字母b
此处省略剩下的24个字母 此处省略剩下的24个字母
<1> 数字1
<2> 数字2
此处省略剩下的8个数字 此处省略剩下的8个数字
<A> 按键shift+a或者字母大写A
<B> 按键shift+b或者字母大写B
此处省略剩下的24个大写字母 此处省略剩下的24个写字母

注:

<a> = <Key-a> = <KeyPress-a> = <KeyRelease-a>
打印字符的基本应用

例子:当我们按下a时,tkinter做出响应

import tkinter

def tab(event):
    print(f"按下了{event.keysym}键")

root = tkinter.Tk()
root.geometry("100x80")
root.bind("<a>", tab)

root.mainloop()

运行结果:
在这里插入图片描述

组合键
组合键 说明
<Shift-Home> Shift+Home
<Alt-Home> Alt+Home
<Control-Home> Ctrl+Home
<Control-A> Ctrl+shift+a

注:

组合键不止这些,可以自由组合

组合键的基本应用

例子:当我们按下Alt+Home时,tkinter做出响应

import tkinter

def tab(event):
    print(f"按下了home键")

root = tkinter.Tk()
root.geometry("100x80")
root.bind("<Alt-Home>", tab)

root.mainloop()

运行结果:
在这里插入图片描述

窗体事件
窗体事件 说明
<Configure> 改变大小或位置
<Visibility> 当组件变为可视状态时触发
<Unmap> 当组件由显示状态变为隐藏状态时触发
<Map> 当组件由隐藏状态变为显示状态时触发
<Expose> 当组件从原本被其他组件遮盖的状态中暴漏出来时触发
<FocusIn> 组件获得焦点时触发
<FocusOut> 组件失去焦点时触发
<Circulate> 当窗体由于系统协议要求在堆栈中置顶或压底时触发
<Colormap> 当窗体的颜色或外貌改变时触发,Tk中忽略此细则
<Property> 当窗体的属性被删除或改变时触发,属于TK的核心
<Destroy> 当组件被销毁时触发
<Activate> 与组件选项中的state项有关,表示组件由不可用变为可用时触发
<Deactiavte> 与组件选项中的state项有关,表示组件由可用变为不可用时候触发
窗体事件绑定的基本应用

例子:获得焦点与失去焦点,由Tab键进行切换

import tkinter

def a(event):
    label.config(text="获取焦点")

def b(event):
    label.config(text="失去焦点")

root = tkinter.Tk()
root.geometry("300x200")

btu = tkinter.Button(root, text="Click")
btu.pack(anchor=tkinter.W)
btu.bind("<FocusIn>", a)
btu.bind("<FocusOut>", b)

btu1 = tkinter.Button(root, text="Other")
btu1.pack(anchor=tkinter.W)


label = tkinter.Label(root, bg="lightgreen", fg="red", height=2, width=12, font="Times 16 bold")
label.pack()

root.mainloop()

运行结果:
在这里插入图片描述
例子:组件由隐藏状态变为显示状态,显示状态变为隐藏状态

from tkinter import *

def show(event):
    b2.config(bg="lightyellow")
    # SystemButtonFace 默认的颜色,就是那个灰色
    b1.config(bg="SystemButtonFace")

def Unshow(event):
    b1.config(bg="lightblue")
    b2.config(bg="SystemButtonFace")

root = Tk()

l1 = Label(root, text='pack_forget')
b3 = Button(root, text='按钮')
b3.bind("<Unmap>", Unshow)
b3.bind("<Map>", show)

# pack_forget 不显示
b1 = Button(root, text='隐藏', command=b3.pack_forget)
b2 = Button(root, text='显示', command=b3.pack)

l1.pack(fill=X)
b1.pack(fill=X)
b2.pack(fill=X)
b3.pack()

root.mainloop()

运行结果:
在这里插入图片描述

Event
Event 说明
widget 事件被触发的控件
.x, .y 鼠标距离窗体左上角的位置(座标)
.x_root, .y_root 鼠标距离屏幕左上角的位置(座标)
.char 键盘事件对应的字符代码
.keysym 键盘事件对应的字符串
.keycode 键盘事件对应的按键码
.num 鼠标事件对应的按键码
.width, .height 控件的新大小
.type 事件类型
Event的基本应用

例子:键盘输入,tkinter响应字符串和按键码(ASCII)

import tkinter

def show(event):
    print(f"{event.keysym}对应的ASCII码:{event.keycode}")

win = tkinter.Tk()
win.geometry("150x100")
win.bind("<Key>", show)

win.mainloop()

运行结果:
在这里插入图片描述

对于ASCII的说明

  每套键盘可能对应的ASCII都不同,所以在这里我并没有写明每个字母、字符、数字的ASCII值,即使写了可能也与大家的ASCII值不同,怎样得知自己键盘的ASCII值呢?

  上述的方法获取是最好验证的,请参照Event的基本应用中的例子

取消绑定

取消绑定xx的方法如下:

# <xxx>是绑定方式
xx.unbind("<xxx>")

例子

import tkinter

def show(event):
    label.config(text="ForPython!")

def choose(x):
    if var.get():
        x.bind("<Button-1>", show)
    else:
        label.config(text="")
        x.unbind("<Button-1>")

root = tkinter.Tk()
root.geometry("300x200")

btu = tkinter.Button(root, text="Click")
btu.pack(anchor=tkinter.W)

var = tkinter.BooleanVar()
cbut = tkinter.Checkbutton(root, text="bind/unbind", variable=var, command=lambda: choose(btu))
cbut.pack(anchor=tkinter.W)


label = tkinter.Label(root, bg="lightgreen", fg="red", height=2, width=12, font="Times 16 bold")
label.pack()

root.mainloop()

运行结果:
在这里插入图片描述

一个事件绑定多个事件处理程序

  使用bind()方法可以绑定一个事件处理程序,tkinter也允许我们执行一个事件绑定多个事件处理程序,同样使用bind()方法,但是新增加的时间处理程序需要在bind()方法内增加参数add = "+"

例子

import tkinter


def show():
    print("???")


def shower(event):
    print("!!!")


root = tkinter.Tk()
button = tkinter.Button(root, text="Click", command=show)
button.pack()
button.bind("<1>", shower, add="+")

root.mainloop()

在这里插入图片描述

程序会先执行bind()绑定的程序,然后再执行Button()command指定的程序

Protocols

Protocols 可以翻译为通信协议,在tkinter内可以解释为窗口管理程序(Windows Manager)与应用程序(Application)之间的通信协议。tkinter也支持使用绑定概念更改此通信协议

例子:退出程序询问是否要退出

import tkinter
from tkinter import messagebox


def show():
    res = messagebox.askokcancel("提示", "请问您确定要退出吗?")
    if res:
        root.destroy()
    else:
        return


root = tkinter.Tk()
root.protocol("WM_DELETE_WINDOW", show)

root.mainloop()

运行结果:
在这里插入图片描述

谢谢观看,笔者会持续更新,如有错误或者建议,请私信我

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章