Wxpython 简明教程

wxPython - Event Handling

与按顺序执行的控制台模式应用程序不同,基于GUI的应用程序是事件驱动的。函数或方法根据用户的动作(如单击按钮、从集合中选择项目或单击鼠标等,称为事件)执行。

Unlike a console mode application, which is executed in a sequential manner, a GUI based application is event driven. Functions or methods are executed in response to user’s actions like clicking a button, selecting an item from collection or mouse click, etc., called events.

在应用程序运行时发生的事件相关的数据存储为从 wx.Event 派生的子类的对象。显示控件(例如按钮)是特定类型事件的源并生成与之关联的Event类对象。例如,单击按钮会发出wx.CommandEvent。此事件数据将调度给程序中的事件处理程序方法。wxPython具有许多预定义的事件绑定程序。一个 Event binder 将特定小部件(控件)、其关联的事件类型以及事件处理程序方法之间的关系封装起来。

Data pertaining to an event which takes place during the application’s runtime is stored as object of a subclass derived from wx.Event. A display control (such as Button) is the source of event of a particular type and produces an object of Event class associated to it. For instance, click of a button emits a wx.CommandEvent. This event data is dispatched to event handler method in the program. wxPython has many predefined event binders. An Event binder encapsulates relationship between a specific widget (control), its associated event type and the event handler method.

例如,要在按钮的单击事件上调用程序的 OnClick() method ,需要以下语句:

For example, to call OnClick() method of the program on a button’s click event, the following statement is required −

self.b1.Bind(EVT_BUTTON, OnClick)

Bind() method 由 wx.EvtHandler 类中的所有显示对象继承。此处 EVT_.BUTTON 是关联按钮点击事件至 OnClick() 方法的绑定器。

Bind() method is inherited by all display objects from wx.EvtHandler class. EVT_.BUTTON here is the binder, which associates button click event to OnClick() method.

Example

在以下示例中,MoveEvent 由拖动顶级窗口(本例中为一个 wx.Frame 对象)而引起,使用 wx.EVT_MOVE 绑定器连接至 OnMove() method 。此代码显示一个窗口。如果使用鼠标移动窗口,其瞬时坐标将显示在控制台上。

In the following example, the MoveEvent, caused by dragging the top level window – a wx.Frame object in this case – is connected to OnMove() method using wx.EVT_MOVE binder. The code displays a window. If it is moved using mouse, its instantaneous coordinates are displayed on the console.

import wx

class Example(wx.Frame):

   def __init__(self, *args, **kw):
      super(Example, self).__init__(*args, **kw)
      self.InitUI()

   def InitUI(self):
      self.Bind(wx.EVT_MOVE, self.OnMove)
      self.SetSize((250, 180))
      self.SetTitle('Move event')
      self.Centre()
      self.Show(True)

   def OnMove(self, e):
      x, y = e.GetPosition()
      print "current window position x = ",x," y= ",y

ex = wx.App()
Example(None)
ex.MainLoop()

上述代码生成以下输出 -

The above code produces the following output −

move event

当前窗口位置 x = 562 y = 309

current window position x = 562 y = 309

当前窗口位置 x = 562 y = 309

current window position x = 562 y = 309

当前窗口位置 x = 326 y = 304

current window position x = 326 y = 304

当前窗口位置 x = 384 y = 240

current window position x = 384 y = 240

当前窗口位置 x = 173 y = 408

current window position x = 173 y = 408

当前窗口位置 x = 226 y = 30

current window position x = 226 y = 30

当前窗口位置 x = 481 y = 80

current window position x = 481 y = 80

从 wx.Event 继承的一些子类在下表中列出 −

Some of the subclasses inherited from wx.Event are listed in the following table −

WxPython 中的事件有两种类型:基本事件和命令事件。基本事件只存在于其源头的窗口中。大多数 wxWidget 会生成命令事件。一个 command event 可以传播到位于类层次结构中源窗口之上的窗口。

Events in wxPython are of two types. Basic events and Command events. A basic event stays local to the window in which it originates. Most of the wxWidgets generate command events. A command event can be propagated to window or windows, which are above the source window in class hierarchy.

Example

以下是事件传播的一个简单示例。完整代码如下:

Following is a simple example of event propagation. The complete code is −

import wx

class MyPanel(wx.Panel):

   def __init__(self, parent):
      super(MyPanel, self).__init__(parent)

      b = wx.Button(self, label = 'Btn', pos = (100,100))
      b.Bind(wx.EVT_BUTTON, self.btnclk)
      self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)

   def OnButtonClicked(self, e):

      print 'Panel received click event. propagated to Frame class'
      e.Skip()

   def btnclk(self,e):
      print "Button received click event. propagated to Panel class"
      e.Skip()

class Example(wx.Frame):

   def __init__(self,parent):
      super(Example, self).__init__(parent)

      self.InitUI()

   def InitUI(self):

      mpnl = MyPanel(self)
      self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)

      self.SetTitle('Event propagation demo')
      self.Centre()
      self.Show(True)

   def OnButtonClicked(self, e):

      print 'click event received by frame class'
      e.Skip()

ex = wx.App()
Example(None)
ex.MainLoop()

在以上代码中,有两个类。 MyPanel ,一个 wx.Panel 子类和 Example,一个 wx.Frame 子类,它是该程序的顶级窗口。一个按钮放置在面板中。

In the above code, there are two classes. MyPanel, a wx.Panel subclass and Example, a wx.Frame subclass which is the top level window for the program. A button is placed in the panel.

这个 Button 对象绑定到一个事件处理程序 btnclk(),它将事件传播到父类(在这个例子中是 MyPanel)。按钮单击会生成一个 CommandEvent , 它可以通过 Skip() 方法传播到它的父对象。

This Button object is bound to an event handler btnclk() which propagates it to parent class (MyPanel in this case). Button click generates a CommandEvent which can be propagated to its parent by Skip() method.

MyPanel 类对象也把接收到的事件绑定到另一个处理程序 OnButtonClicked()。该函数又依次把事件发送给它的父对象,也就是 Example 类。以上代码会产生以下输出 −

MyPanel class object also binds the received event to another handler OnButtonClicked(). This function in turn transmits to its parent, the Example class. The above code produces the following output −

event handling output
Button received click event. Propagated to Panel class.
Panel received click event. Propagated to Frame class.
Click event received by frame class.