wxPython - 事件处理



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

与应用程序运行时发生的事件相关的数据存储为从wx.Event派生的子类的对象。显示控件(如按钮)是特定类型事件的源,并生成与其关联的 Event 类对象。例如,单击按钮会发出 wx.CommandEvent。此事件数据被分派到程序中的事件处理程序方法。wxPython 具有许多预定义的事件绑定器。事件绑定器封装了特定窗口小部件(控件)、其关联的事件类型和事件处理程序方法之间的关系。

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

self.b1.Bind(EVT_BUTTON, OnClick)

Bind() 方法由所有显示对象从 wx.EvtHandler 类继承。此处的 EVT_.BUTTON 是绑定器,它将按钮单击事件与 OnClick() 方法关联。

示例

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

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

以上代码产生以下输出:

Move Event

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

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

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

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

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

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

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

以下表格列出了从 wx.Event 继承的一些子类:

序号 事件和描述
1

wxKeyEvent

当按下或释放键时发生

2

wxPaintEvent

每当需要重新绘制窗口内容时生成

3

wxMouseEvent

包含任何由于鼠标活动(如鼠标按钮按下或拖动)引起的事件的数据

4

wxScrollEvent

与可滚动控件(如 wxScrollbar 和 wxSlider)相关联

5

wxCommandEvent

包含源自许多窗口小部件(如按钮、对话框、剪贴板等)的事件数据。

6

wxMenuEvent

不同的菜单相关事件,不包括菜单命令按钮单击

7

wxColourPickerEvent

wxColourPickerCtrl 生成的事件

8

wxDirFilePickerEvent

FileDialog 和 DirDialog 生成的事件

wxPython 中的事件有两种类型。基本事件和命令事件。基本事件保留在其起源窗口的本地。大多数 wxWidgets 生成命令事件。命令事件可以传播到窗口或窗口,这些窗口在类层次结构中位于源窗口的上方。

示例

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

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 子类,它是程序的顶级窗口。一个按钮放置在面板中。

此 Button 对象绑定到一个事件处理程序 btnclk(),该处理程序将其传播到父类(在本例中为 MyPanel)。按钮单击生成一个CommandEvent,可以通过 Skip() 方法将其传播到其父级。

MyPanel 类对象还将接收到的事件绑定到另一个处理程序 OnButtonClicked()。此函数又将其父级 Example 类进行传输。以上代码产生以下输出:

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.
广告