1

最近在学习wxPythonvia wxPython in Action,但是卡在了第3章,特别是对Figure 3.3's Skip()diamond的解释

书中Step 3 Locating the binder object写道:

如果没有为对象本身找到绑定器,则处理将向上遍历类层次结构以查找在对象的超类中定义的绑定器—— (1)这与在容器层次结构中向上走不同下一步。

但在下一步中,Step 4 Determining whether to continue processing写道:

事件处理程序通过调用 wx.Event 方法 Skip() 请求更多处理。如果调用 Skip() 方法,则处理继续,并且(2) 在(3) 超类中定义的任何处理程序都会在该步骤中找到并执行。可以在处理程序中的任何位置调用 Skip() 方法。Skip() 方法在事件实例中设置一个标志,wxPython 在处理程序方法完成后检查该标志。在清单 3.3 中,OnButtonClick() 没有调用 Skip(),因此在这种情况下,事件过程在处理程序方法结束时完成。其他两个事件处理程序确实调用 Skip() (4),因此系统将继续搜索匹配的事件绑定(5) 最终调用本地小部件的鼠标进入和离开事件的默认功能,例如鼠标悬停事件。

我的问题与我在文章中标记的数字有关:

(1)在我的理解和其他一些谷歌资料中,传播是容器层次结构中发生的事情,而不是类层次结构,这是正确的吗?

(2) 认真的吗?执行任何处理程序?不是匹配实例和事件组合的那些?

(3)这里的超类是正确的吗?它不应该是父窗口吗?

(4) 我认为这条线与问题2相矛盾,所以可能没有执行任何处理程序,只是那些与实例和事件组合匹配的处理程序?

(5) 什么是default functionality? 它是如何调用的?

如果有人感兴趣,listing-3.3.py 在这里:

import wx


class MouseEventFrame(wx.Frame):

    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, 'Mouse Events',
                          size=(300, 200))
        self.panel = wx.Panel(self)
        self.button = wx.Button(self.panel,
                                label='Not Over', pos=(100, 15))
        self.Bind(wx.EVT_BUTTON, self.OnButtonClick, self.button)
        self.button.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
        self.button.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)

    def OnButtonClick(self, event):
        self.panel.SetBackgroundColour('Green')
        self.panel.Refresh()

    def OnEnterWindow(self, event):
        self.button.SetLabel('Over Me!')
        event.Skip()

    def OnLeaveWindow(self, event):
        self.button.SetLabel('Not Over')
        event.Skip()


if __name__ == '__main__':
    app = wx.App()
    frame = MouseEventFrame(parent=None, id=-1)
    frame.Show()
    app.MainLoop()
4

1 回答 1

6

当生成与某个对象关联的事件时,处理程序查找的顺序为:

  1. wxApp::FilterEvent()
  2. 推送到对象本身的任何事件处理程序。我什至不确定这是否在 wxPython 中公开,无论如何都不应该再使用它。
  3. 对象本身,从在最派生类中注册的处理程序开始,并继续在基类中定义的处理程序。
  4. 如果事件是“可传播的”(默认情况下是这种情况,wxCommandEvent但不是,比如说,wxMouseEvent),并且如果对象是一个窗口,那么对象的所有父窗口,递归。
  5. wxTheApp本身。
  6. 最后,使用底层工具包级别的事件的默认处理程序。如果有的话,它的作用取决于确切的事件类型和平台,但对于某些事件,让它被调用非常重要,特别是对于焦点事件,您必须让默认的本机控制处理程序获取它们才能更新它们专注的状态。

现在,怎么样Skip()?通常,使用搜索时找到的第一个处理程序,并且事件处理在那里停止。event.Skip()但是,如果处理程序在其执行期间调用,则会跳过此事件处理程序并继续搜索。即要理解的重要一点是它Skip()不会跳过事件,即使它是在事件对象上调用的。相反,它会跳过调用它的事件处理程序。

希望您现在明白为什么调用处理程序很重要event.Skip()wxFocusEvent

于 2013-11-11T12:25:01.043 回答