美文网首页
十一、事件绑定

十一、事件绑定

作者: 蝉时雨丶 | 来源:发表于2020-07-06 15:28 被阅读0次

    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()
    

    相关文章

      网友评论

          本文标题:十一、事件绑定

          本文链接:https://www.haomeiwen.com/subject/edawqktx.html