1.Widget的command参数
在前面介绍了许多Widget控件,许多Widget的构造方法内可以看到command参数,例如,功能按钮(Button)、
数值滚动条(Scale)等。其实这就是一个Widget的事件绑定的概念,当按钮事件发生、当数值滚动条值改变······
就可以通过command=callback,设计callback函数,这个callback函数就是事件处理程序。
样例:当单击功能按钮或是选择复选框时,窗口下方会做出所执行的动作。
from tkinter import *
def pythonClicked():
if varPython.get():
lab.config(text="Select Python")
else:
lab.config(text="Unselect Python")
def javaClicked():
if varJava.get():
lab.config(text="Select Java")
else:
lab.config(text="Unselect Java")
def buttonClicked():
lab.config(text="Button clicked")
root=Tk()
root.title("ch11_1")
root.geometry("300x180")
btn=Button(root,text="Click me",command=buttonClicked)
btn.pack(anchor=W)
varPython=BooleanVar()
cbnPython=Checkbutton(root,text="Python",variable=varPython,
command=pythonClicked)
cbnPython.pack(anchor=W)
varJava=BooleanVar()
cbnJava=Checkbutton(root,text="Java",variable=varJava,
command=javaClicked)
cbnJava.pack(anchor=W)
lab=Label(root,bg="yellow",fg="blue",
height=2,width=12,
font="Times 16 bold")
lab.pack()
root.mainloop()
2.事件绑定
事件绑定
在tkinter应用程序中最后一个指令是mainloop(),这个方法是让程序进入事件等待循环,除了
Widget控件状态改变可以调用相对应的事件处理程序外,tkinter也提供了为事件绑定处理程序
的机制。它的语法格式如下:
·widget.bind(event,handler)
·widget.bind_class(class,event,handler)
绑定某些类别,它接受三个参数, 第一个参数是类名,第二个参数是事件类型,第三个参数 是相应的操作,
比如 w.bind_class(“Entry”, “<Control-V>”,my_paste)。它就是绑定了所有的所有的 输入框的 Ctrl+V 表示粘贴。
·widget.bind_all(event,handler)
全程序级别的绑定,它的参数类 型和 bind 一样,它通常用于全局的快捷键,比如 F1 通常 是用来打开帮助
上述绑定语法中widget是事件的来源,可以是root窗口对象,或是任意的Widget控件,例如,
功能按钮、选项按钮、复选框······handler是事件处理程序。
鼠标相关的事件如下表所示:
鼠标事件 说明:
<Button-1> 单击鼠标左键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Button-2> 单击鼠标中键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Button-3> 单击鼠标右键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Button-4> 鼠标滑轮向上滚动,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Button-5> 鼠标滑轮向下滚动,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Motion> 鼠标移动,鼠标光标相对控件位置会被存入事件对象的x和y变量
<B1-Motion> 拖拽,按住鼠标左键再移动鼠标,鼠标光标相对控件位置会被存入事件对象的x和y变量
<B2-Motion> 拖拽,按住鼠标中键再移动鼠标,鼠标光标相对控件位置会被存入事件对象的x和y变量
<B3-Motion> 拖拽,按住鼠标右键再移动鼠标,鼠标光标相对控件位置会被存入事件对象的x和y变量
<ButtonRelease-1> 放开鼠标左键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<ButtonRelease-2> 放开鼠标中键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<ButtonRelease-3> 放开鼠标右键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Double-Button-1> 连续两下鼠标左键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Double-Button-2> 连续两下鼠标左键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Double-Button-3> 连续两下鼠标左键,鼠标光标相对控件位置会被存入事件对象的x和y变量
<Enter> 鼠标光标进入Widget控件
<Leave> 鼠标光标离开Widget控件
键盘相关的事件如下表所示:
<FocusIn> 键盘焦点进入Widget控件
<FocusOut> 键盘焦点离开Widget控件
<Return> 按下Enter键,键盘所有键都可以绑定,例如,Cancel、BackSpace、Tab、Shift、Ctrl、Alt、End、Esc、Next(Page Down)、Prior(Page Up)、Home、End、Right、Left、Up、Down、F1~F2、Scroll Lock、Num Lock
<Shift-Up> 按住Shift时按下Up键
<Alt-Up> 按住Alt时按下Up键
<Ctrl-Up> 按住Ctrl键时按下Up键
控件相关事件如下表所示:
控件事件 说明
<Config> 更改Widget控件的大小和位置,新控件大小的width与height会存储在event对象内。
了解以上事件绑定后,其实我们已经可以试着学习自我设计事件绑定处理程序,同时将事件处理程序与一般事件绑定在一起。
我们从先前的学习中可以知道,单击功能按钮时可以执行某个动作,所使用的是Button()内增加command参数,然后单击
功能按钮时让程序执行command所指定的方法。
其实设计功能按钮程序时,若是在Button()内省略command参数,所产生的影响是单击功能按钮时没有动作。然后我们可以
使用本节的知识重新让单击功能按钮有动作产生,假设功能按钮对象是btn,可以使用下列方式建立单击与事件的绑定。
btn.bind("<Button-1>",event_handler)
样例:使用事件绑定方式让单击Check me按钮后可以列出"Button clicked"字符串。对这个程序而言,功能按钮就是bind()方法
的事件来源。
from tkinter import *
def pythonClicked():
if varPython.get():
lab.config(text="Select Python")
else:
lab.config(text="Unselect Python")
def javaClicked():
if varJava.get():
lab.config(text="Select Java")
else:
lab.config(text="Unselect Java")
def buttonClicked(event):
lab.config(text="Button clicked")
root=Tk()
root.title("ch11_1_1")
root.geometry("300x180")
btn=Button(root,text="Click me")
btn.pack(anchor=W)
btn.bind("<Button-1>",buttonClicked)
varPython=BooleanVar()
cbnPython=Checkbutton(root,text="Python",variable=varPython,
command=pythonClicked)
cbnPython.pack(anchor=W)
varJava=BooleanVar()
cbnJava=Checkbutton(root,text="Java",variable=varJava,
command=javaClicked)
cbnJava.pack(anchor=W)
lab=Label(root,bg="yellow",fg="blue",
height=2,width=12,
font="Times 16 bold")
lab.pack()
root.mainloop()
image.png
鼠标绑定的基本应用
样例:
鼠标事件的基本应用,这个程序在执行时会建立300x180大小的窗口,当单击鼠标左键时,在Python Shell窗口中会列出单击
事件时的坐标。
from tkinter import *
def callback(event):
print("Clicked at",event.x,event.y)
root=Tk()
root.title("ch11_2")
frame=Frame(root,width=300,height=180)
frame.bind("<Button-1>",callback)
frame.pack()
root.mainloop()
在程序绑定的事件处理程序中必须留意,callback(event)需有参数event,event名称可以自定义,
这是因为事件会传递事件对象给此事件处理程序。
样例二:移动鼠标时可以在窗口右下方看到鼠标目前的坐标。
from tkinter import *
def mouseMotion(event):
x=event.x
y=event.y
textvar="Mouse location -x:{},y:{}".format(x,y)
var.set(textvar)
root=Tk()
root.title("ch11_2_1")
root.geometry("300x180")
x,y=0,0
var=StringVar()
text="Mouse location -x:{},y:{}".format(x,y)
var.set(text)
lab=Label(root,textvariable=var)
lab.pack(anchor=S,side=RIGHT,padx=10,pady=10)
root.bind("<Motion>",mouseMotion)
root.mainloop()
键盘绑定的基本应用
样例:这是一个测试键盘绑定的程序,在执行时会出现窗口,若是按Esc键,将出现对话框询问是否离开,单击"是"
按钮可以离开程序,单击"否"按钮程序继续。
from tkinter import *
from tkinter import messagebox
def leave(event):
ret=messagebox.askyesno("ch11_4","是否离开?")
if ret==True:
root.destroy()
else:
return
root=Tk()
root.title("ch11_4")
root.bind("<Escape>",leave)
lab=Label(root,text="测试Esc键",
bg="yellow",fg="blue",
height=4,width=15,
font="Times 12 bold")
lab.pack(padx=30,pady=30)
root.mainloop()
样例2:这个程序在执行时用<Key>作绑定事件key,整个程序执行时会将所按a···z键打印出来。这个程序第4行
使用了比较少使用的repr()函数,这个函数会将参数处理成字符串。
from tkinter import *
def key(event):
print("按了"+repr(event.char)+"键")
root=Tk()
root.title("ch11_5")
root.bind("<Key>",key)
root.mainloop()
键盘与鼠标事件绑定的陷阱
Frame框架本身是一个Widget控件,在使用框架时需特别小心获得焦点的概念,当事件绑定与Frame有关时,
必须在Frame获得焦点时,键盘绑定才可生效。
样例:键盘与鼠标绑定Frame对象的应用。
from tkinter import *
def key(event):
print("按了 "+repr(event.char) + " 键")
def coordXY(event):
frame.focus_set()
print("鼠标坐标 :",event.x,event.y)
root=Tk()
root.title("ch11_6")
frame=Frame(root,width=100,height=100)
frame.bind("<Key>",key)
frame.bind("<Button-1>",coordXY)
frame.pack()
root.mainloop()
这个程序在执行时必须将鼠标光标放在窗口内,同时先有鼠标单击,这时frame.focus_set()让Widget
控件frame获得焦点,然后按键才可以动作。
3.取消绑定
取消绑定obj的方法如下:
obj.unbind("<xxx>") # <xxx>是绑定方式
样例:这是一个tkinter按钮程序,在tkinter按钮下方有复选框bind/unbind。如果勾选这个复选框,相当于
有绑定,在单击tkinter按钮时Python Shell会列出字符串"I like tkinter"。如果没有选择这个复选框,相当于
没有绑定,在单击tkinter按钮时Python Shell没有任何动作产生。
from tkinter import *
def buttonClicked(event):
print("I like tkinter")
def toggle(onoff):
if var.get()==True:
onoff.bind("<Button-1>",buttonClicked)
else:
onoff.unbind("<Button-1>")
root=Tk()
root.title("ch11_7")
root.geometry("300x180")
btn=Button(root,text="tkinter")
btn.pack(anchor=W,padx=10,pady=10)
var=BooleanVar()
cbtn=Checkbutton(root,text="bind/unbind",variable=var,
command=lambda:toggle(btn))
cbtn.pack(anchor=W,padx=10)
root.mainloop()
当按钮与复选框绑定时,单击tkinter按钮会在Python Shell窗口中打印"I like tkinter"
4.一个事件绑定多个事件处理程序
之前程序中使用bind()方法时可以绑定一个事件处理程序,tkinter也允许我们执行一个事件绑定多个事件处理程序,
同样是使用bind()方法,但是新增加的事件处理程序需要在bind()方法内增加参数add="+"。
样例:
一个单击按钮功能动作,会有两个事件处理程序做出响应。
from tkinter import *
def btnClicked1():
print("Command event handler,I like tkinter")
def btnClicked2(event):
print("Bind event handler,I like tkinter")
root=Tk()
root.title("ch11_8")
root.geometry("300x180")
btn=Button(root,text="tkinter",
command=btnClicked1)
btn.pack(anchor=W,padx=10,pady=10)
btn.bind("<Button-1>",btnClicked2,add="+")
root.mainloop()
若单击tkinter功能按钮,可以在Python Shell窗口中看到执行两个事件处理程序的结果。
从上述我们也发现了当单击按钮事件发生时,程序会先执行bind()绑定的程序,然后再执行
Button()内command指定的程序。
5.Protocols
Protocols可以翻译为通信协议,在tkinter内可以解释为窗口管理程序(Windows Manager)与应用
程序(Application)之间的通信协议。tkinter也支持使用绑定概念更改此通信协议。
样例:单击通信协议(Protocols)内容窗口右上角的x按钮可以关闭窗口,它的名称是WM_DELETE_WINDOW。
这个程序会修改此协议,改为单击此按钮后增加Messagebox,询问"结束或取消",若是单击"确定"按钮才会
结束此程序。
from tkinter import *
from tkinter import messagebox
def callback():
res=messagebox.askokcancel("OKCANCEL","结束或取消?")
if res==True:
root.destroy()
else:
return
root=Tk()
root.title("ch11_9")
root.geometry("300x180")
root.protocol("WM_DELETE_WINDOW",callback)
root.mainloop()
网友评论