wxpython笔记:Wxpython事件处理机制

在wxpython中关于事件的名称解释:

  • 事件(event):在你的应用程序期间发生的事情,它要求有一个响应。
  • 事件对象(event object):在wxPython中,它具体代表一个事件,其中包括了事件的 数据等属性。它是类wx.Event或其子类的实例,子类如wx.CommandEvent和 wx.MouseEvent。
  • 事件类型(event type):wxPython分配给每个事件对象的一个整数ID。事件类型给出 了关于该事件本身更多的信息。例如,wx.MouseEvent的事件类型标识了该事件是 一个鼠标单击还是一个鼠标移动。
  • 事件源(event source):任何wxPython对象都能产生事件。例如按钮、菜单、列表框 和任何别的窗口部件。
  • 事件驱动(event driven):一个程序结构,它的大部分时间花在等待或响应事件上。
  • 事件队列(event queue):已发生的但未处理的事件的一个列表。
  • 事件处理器(event handler):响应事件时所调用的函数或方法。也称作处理器函数或 处理器方法。
  • 事件绑定器(event binder):一个封装了特定窗口部件,特定事件类型和一个事件处理器的wxPython对象。为了被调用,所有事件处理器必须用一个事件绑定器注册。 wx.EvtHandler:一个wxPython类,它允许它的实例在一个特定类型,一个事件源, 和一个事件处理器之间创建绑定。注意,这个类与先前定义的事件处理函数或方法不 是同一个东西。

 

 

事件类

在wxPython中,代表事件的是事件对象。事件对象是类wx.Event或其子类的一个实例。
父类wx.Event相对小且抽象,它只是包含了对所有事件的一些通常的信息。wx.Event的各个子类都添加了更多的信息。
一个事件类可以有多个事件类型,每个都对应于一个不同的用 户行为

以下是wx.Event的重要的子类(事件类) :

  • wx.CloseEvent:当一个框架关闭时触发。这个事件的类型分为一个通常的框架关闭 和一个系统关闭事件。
  • wx.KeyEvent::键盘事件, 例如当一个键被按下或释放时发生。
  • wx.PaintEvent:当窗口的内容需要被重画时触发。
  • wx.MouseEvent:鼠标事件,如按下鼠标按钮或拖动。
  • wx.ScrollEvent 关联像wxScrollbar和wxSlider滚动控制。
  • wx.CommandEvent::与窗口部件的简单的各种交互都将触发这个事件,如按钮单 击、菜单项选择、单选按钮选择。这些交互有它各自的事件类型。许多更复杂的窗口 部件,如列表等则定义wx.CommandEvent的子类。事件处理系统对待命令事件与其 它事件不同。
  • wx.MenuEvent:不同的菜单相关的事件但不包括菜单命令按钮点击
  • wx.ColourPickerEvent:wxColourPickerCtrl生成的事件。
  • wx.DirFilePickerEvent:通过FileDialog和DirDialog生成的事件。
  • wx.SizeEvent:当窗口的大小或其布局改变时触发。
  • wx.TimerEvent:可以由类wx.Timer类创建,它是定期的事件。

更多具体的事件类:官网文档

 

事件绑定

事件绑定器被用于将一个wxPython窗口部件(事件源)与一个事件对象和一个处理器函数连接起来。
这个连接使得wxPython系统能够通过执行处理器函数中的代码 来响应相应窗口部件上的事件。
在wxPython中,任何能够响应事件的对象都是 wx.EvtHandler的子类。
所有窗口对象都是wx.EvtHandler的子类,因些在wxPython应用程序中的每个窗口部件都能够响应事件。
类wx.EvtHandler也能够被非窗口部件对象所使用,如wx.App,因此事件处理功能不是限于可显示的窗 口部件。
我们所说的窗口部件能响应事件的意思是:该窗口部件能够创建事件绑定,在分派期间wxPython能够识别该事件绑定
由绑定器调用的在事件处理 器函数中的实际代码不是必须位于一个wx.EvtHandler类中。

wx.EvtHandler有一个方法是Bind(),它创建事件绑定。该方法的用法如下:

Bind(event,handler,source=None,id=wx.ID_ANY,id2=wx.ID_ANY)

Bind()函数将一个事件和一个对象与一个事件处理器函数关联起来。

  • 参数 event是必选的,事件类型。
  • 参数 handler也是必选的,它是一个可调用的Python对象,通常是一个被绑定的方法 或函数。处理器必须是可使用一个参数(事件对象本身)来调用的。
  • 参数 handler可以是None,这种情况下,事件没有关联的处理器。
  • 参数source是产生 该事件的源窗口部件,这个参数在触发事件的窗口部件与用作事件处理器的窗口部件不相同时使用。

wxpython笔记:Wxpython事件处理机制_第1张图片

最常使用的wx.EvtHandler的方法:

  • AddPendingEvent(event):将这个event参数放入事件处理系统中。类似于 ProcessEvent(),但它实际上不会立即触发事件的处理。相反,该事件被增加到事件 队列中。适用于线程间的基于事件的通信。
  • Bind(event,handler,source=None,id=wx.ID_ANY,id2=wx.ID_ANY):事件绑定。
  • GetEvtHandlerEnabled() SetEvtHandlerEnabled(boolean):如果处理器当前正在处理事件,则属性为True, 否则为False。
  • ProcessEvent(event):把event对象放入事件处理系统中以便立即处理。

 

事件驱动编程

从用户的角度上来看,wxPython程序大部分时间什么也不做,一直闲着直 到用户或系统做了些什么来触发这个wxPython程序动作。
wxPython程序的结构 就是一个事件驱动程序体系的例子。
图3.1是事件处理循环的示意,它展示了主程序的生命、用户事件、和分派到的处理器函数。

wxpython笔记:Wxpython事件处理机制_第2张图片

事件驱动系统的主循环类似于客户服务呼叫中心的操作者。当没有呼叫的 进入的时候,这个操作者处于等待状态。
当一个事件发生的时候,如电话铃响了,这个操作者开始一个响应过程,他与客户交谈直到他获得足够的信息以分 派该客户给一个合适的回答者。
然后操作者等待下一个事件。
尽管每个事件驱动系统之间有一些不同,但它们有很多相似的地方。下面列出了事件驱动程序结构的主要特点:
1、在初始化设置之后,程序的大部分时间花在了一个空闭的循环之中。 进入这个循环就标志着程序与用户交互的部分的开始,退出这个循环就标志结束。在wxPython中,这个循环的方法是:wx.App.MainLoop(),并且在你的脚本 中显式地被调用。当所有的顶级窗口关闭时,主循环退出。
2、程序包含了对应于发生在程序环境中的事情的事件。事件通常由用户的行为触发,但是也可以由系统的行为或程序中其他任意的代码。在wxPython中,所有的事件都是类wx.Event或其子类的一个实例。每个事件都有一个事件 类型属性,它使得不同的事件能够被辨别。例如,鼠标释放和鼠示按下事件都 被认为是同一个类的实例,但有不同的事件类型。
3、作为这个空闭的循环部分,程序定期检查是否有任何请求响应事情发生。有两种机制使得事件驱动系统可以得到有关事件的通知。最常被wxPython使用的方法是,把事件传送到一个中心队列,由该队列触发相应事件的处理。 另一种方法是使用轮询的方法,所有可能引发事件的事件主被主过程定期查询 并询问是否有没有处理的事件。
4、当事件发生时,基于事件的系统试着确定相关代码来处理该事件,如果有,相关代码被执行。在wxPython中,原系统事件被转换为wx.Event实例, 然后使用wx.EvtHandler.ProcessEvent()方法将事件分派给适当的处理器代码。图 3.3呈现了这个过程:
事件机制的组成部分是事件绑定器对象和事件处理器。事件绑定器是一个 预定义的wxPython对象。每个事件都有各自的事件绑定器。事件处理器是一个函数或方法,它要求一个wxPython事件实例作为参数。当用户触发了适当的事件时,一个事件处理器被调用。

 

事件处理过程

wxpython笔记:Wxpython事件处理机制_第3张图片

事件处理过程开始于触发事件的对象。通常,wxPython首先在触发对象中查找匹配事件类型的被绑定的处理器函数。如果找到,则相应的方法被执行。

否则,wxPython将检查该事件是否传送到了上一级的容器。如果是的话,父窗口部件将被检查,这样一级一级向上寻找,直到wxPython找到了一个处理器函 数或到达了顶级窗口。

如果事件没有传播,在处理过程完成之前,wxPython仍将为了处理器函数而检查应用程序对象。

第一步,创建事件

事件首先被交给创建事件的对象。对于按钮敲击,这个对象是按钮;对于鼠标进入事件,这个对象是所进入的窗口部件。

第二步,确定事件对象是否被允许处理事件

通过调用wx.EvtHandler的SetEvtHandlerEnabled(boolean)方法,一个窗口可以被设置为允许或不允许事件处理。不允许事件处理的结果是该窗口部件在事 件处理中被完全绕过,与该对象关联的绑定对象也不会被搜索,并且在这步中 的处理没有向下的分支。

第三步 定位绑定器对象

然后ProcessEvent()方法寻找一个绑定器对象,该绑定器对象确定当前对象和事件类型之间的绑定。
如果对象自身的绑定器没有被找到,那么向上到该对象的超类中去寻找。 如果一个绑定器对象被发现,wxPython调用相关的处理器函数。在处理器被调用后,该事件的事件处理停止,除非处理器函数显式地要求作更多的处理

第四步 决定是否继续处理

在调用了第一个事件处理器之后,wxPython查看是否有进一步的处理要 求。事件处理器通过调用wx.Event的方法Skip()要求更多的处理。如果Skip()方法被调用,那么处理将继续,并且任何定义在超类中的处理器在这一步中被发现并执行。

第五步 决定是否展开

一个事件是否向上展开至容器级,这是每个事件实例的一个动态属性,尽管实际上默认值几乎总是使用那几个。默认情况,只有wx.CommandEvent及其 子类的实例向上展开至容器级。其它的所有事件不这样做。

 

总结

1、wxPython应用程序使用基于事件的控制流。应用程序的大部分时间花 费在一个主循环中,等待事件并分派它们到适当的处理器函数。
2、所有的wxPython事件类型是wx.Event类的子类,事件对象是这些类的实例。低级的事件,如鼠标敲击, 被用来建立高级的事件,如按钮敲击或菜单项选择。这些由wxPython窗口部件 引起的高级事件是类wx.CommandEvent的子类。大多的事件类通过一个事件类 型字段被进一步分类,事件类型字段区分事件。
3、为了捕获事件和函数之间的关联,wxPython使用类wx.PyEventBinder的 实例。类wx.PyEventBinder有许多预定义的实例,每个都对应于一个特定的事 件类型。每个wxPython窗口部件都是类wx.EvtHandler的子类。类wx.EvtHandler 有一个方法Bind(),它通常在初始化时被调用,所带参数是一个事件绑定器实 例和一个处理器函数。根据事件的类型,别的wxPython对象的ID可能也需要被 传递给Bind()调用。
4、事件通常被发送给产生它们的对象,以搜索一个绑定对象,这个绑定 对象绑定事件到一个处理器函数。如果事件是命令事件,这个事件沿容器级向 上传递直到一个窗口部件被发现有一个针对该事件类型的处理器。一旦一个事 件处理器被发现,对于该事件的处理就停止,除非这个处理器调用了该事件的 Skip()方法。你可以允许多个处理器去响应一个事件,或去核查该事件的所有 默认行为。主循环的某些方面可以使用wx.App的方法来控制。
5、在wxPython中可以创建自定义事件,并作为定制(自定义)的窗口部 件的行为的一部分。自定义的事件是类wx.PyEvent的子类,自定义的命令事件 是类wx.PyCommandEvent的子类。为了创建一个自定义事件,新的类必须被定 义,并且关于每个事件类型(这些事件类型被这个新类所管理)的绑定器必须 被创建。最后,这个事件必须在系统的某处被生成,这通过经由ProcessEvent() 方法传递一个新的实例给事件处理器系统来实现。

你可能感兴趣的:(wxpython笔记:Wxpython事件处理机制)