wxPython Cookbook(Chatper2)Part 1

来源:互联网 发布:php curl 异常处理 编辑:程序博客网 时间:2024/05/20 05:25
在一个事件驱动系统(event-driven system)中,事件(event)是用来连接框架内的动作和与事件相关的回调函数(callback function)的。基于事件驱动框架的应用通过利用事件来了解何时来对用户或系统触发的动作来做出反应。在一个用户接口中(user interface),事件是一个来了解何时按钮被按下,何时菜单被选择或用户与应用交互过程中其它广泛的动作。正如你所看到的那样,在创建一个应用的过程中了解如何应对应用生命周期内的事件是十分重要的。
处理事件
wxPython是一个事件驱动系统。该系统的应用是十分直接和普遍的。处理事件的基本模式是相似的,而无论你的应用与之互动的控件及事件类型。这一部分我们将介绍在wxPython中处理事件的基础。
How to do it?
import wxclass MyFrame(wx.Frame):    def __init__(self, parent, *args, **kwargs):        super(MyFrame, self).__init__(parent, *args, **kwargs)                self.panel = wx.Panel(self)        self.btn1 = wx.Button(self.panel, label = "Push Me")        self.btn2 = wx.Button(self.panel, label = "Push Me too")                sizer = wx.BoxSizer(wx.HORIZONTAL)        sizer.Add(self.btn1, 0, wx.ALL, 10)        sizer.Add(self.btn2, 0, wx.ALL, 10)        self.panel.SetSizer(sizer)                self.Bind(wx.EVT_BUTTON, self.OnButton, self.btn1)        self.Bind(wx.EVT_BUTTON, lambda event: self.btn1.Enable(not self.btn1.Enabled), self.btn2)                sizer.Fit(self)    def OnButton(self, event):        event_id = event.GetId()        event_obj = event.GetEventObject()        print "Button 1 Clicked: "        print "ID=%d" % event_id        print "object=%s" % event_obj.GetLabel()if __name__ == "__main__":    app = wx.PySimpleApp(False)    MyFrame(None).Show()    app.MainLoop()

How it works?
在上面代码中值得留意的是那两个Bind函数调用。Bind方法是用来连接一个事件处理函数(event handler)和一个可能发送去控件的事件。事件通常在窗口层级中向上传播而非向下。在这个例子中,我们把按钮事件(button event)绑定在框架上(Frame),但是事件实际上是由面板(panel)的子控件按钮(Button)产生的。框架对象(Frame)是在层级的顶部,其包含了面板(Panel),而面板则是两个按钮(button)的容器。正因如此,所以当事件没有被按钮或面板处理时,它将传递到框架上,在这里我们OnButton处理函数被调用。
Bind方法有两个必要的参数
  • 事件对象(EVT_FOO)
  • 一个以事件对象为第一个参数的可调用对象。这个事件处理函数将在事件发生时被调用
可选的参数是用来指出绑定事件处理函数的源控件。在例子中,我们通过在第三个参数明确指出按钮对象来讲我们每个按钮都绑定在一个处理函数上。EVT_BUTTON是当用户应用中按钮被按下时产生的。当第一个按钮被按下,OnButton将被调用来通知我们的程序事件触发了。这个事件对象将作为我们事件处理函数的第一个参数。事件对象有一系列方法来获取事来源的控件信息。每个事件都有不同是数据,这依托于事件所产生的源控件。
对于我们第二个按钮,我们用lambada函数来作为一个简便的事件处理函数,而非重新定义一个函数。这是一个吃力简单动作的便捷方法。

理解事件传递
在wxPython中有两类行为不同的事件类型(event object):
  • 基本事件(Events)
  • 命令事件(Command Events)
基本事件是那些不会在窗口层级中向上传播的事件,它们只会停留在产生它们的窗口里。第二种事件是命令事件,它也是最为常见的事件,不同于基本事件,它是会在事件层级中向上传播直到被应用对象中的处理函数处理。这个部分我们将展示如何理解,应用事件的传播。
How to do it?
import wxID_BUTTON1 = wx.NewId()ID_BUTTON2 = wx.NewId()class MyApp(wx.App):    def OnInit(self):        self.frame = MyFrame(None, title = "Event Propagation")        self.SetTopWindow(self.frame)        self.frame.Show()                self.Bind(wx.EVT_BUTTON, self.OnButtonApp)                return True        def OnButtonApp(self, event):        event_id = event.GetId()        if event_id == ID_BUTTON1:            print "BUTTON ONE Event reached the App Object"            class MyFrame(wx.Frame):    def __init__(self, parent, *args, **kwargs):        super(MyFrame, self).__init__(parent, *args, **kwargs)                self.panel = MyPanel(self)        self.btn1 = wx.Button(self.panel, ID_BUTTON1, "Propagates")        self.btn2 = wx.Button(self.panel, ID_BUTTON2, "Doesn't Propagates")                sizer = wx.BoxSizer(wx.HORIZONTAL)        sizer.Add(self.btn1, 0, wx.ALL, 10)        sizer.Add(self.btn2, 0, wx.ALL, 10)        self.panel.SetSizer(sizer)        sizer.Fit(self)                self.Bind(wx.EVT_BUTTON, self.OnButtonFrame)            def OnButtonFrame(self, event):        event_id = event.GetId()        if event_id == ID_BUTTON1:            print "BUTTON One event reached the Frame"            event.Skip()        elif event_id == ID_BUTTON2:            print "BUTTON TWO event reached the Frame"class MyPanel(wx.Panel):    def __init__(self, parent):        super(MyPanel, self).__init__(parent)                self.Bind(wx.EVT_BUTTON, self.OnPanelButton)        def OnPanelButton(self, event):        event_id = event.GetId()        if event_id == ID_BUTTON1:            print "BUTTON One event reached the Panel"            event.Skip()        elif event_id == ID_BUTTON2:            print "BUTTON Two event reached the Panel"if __name__ == "__main__":    app = MyApp(False)    app.MainLoop()

How it works?
事件处理函数链是从事件触发的控件开始被调用的。在这次例子中,这将是我们的两个按钮。窗口的每个层级都绑定这一个处理函数,它将接受任意一个按钮的事件。当点击第一个按钮,将展示出所有被调用的处理函数。这是因为对于第一个按钮我们调用了Skip方法。Skip方法将把事件传播到层级中更高的一级。从打印在终端上的三条语句我们就可以验证这一点。与之对比,在点击第二个按钮的时候由于没有调用Skip方法,所以只有一个处理函数被调用。
0 0
原创粉丝点击