wxPython - 事件处理
与以顺序方式执行的控制台模式应用程序不同,基于 GUI 的应用程序是事件驱动的。函数或方法的执行是为了响应用户的操作,例如单击按钮、从集合中选择项目或鼠标单击等,称为事件。
与应用程序运行时发生的事件相关的数据存储为派生自wx.Event的子类的对象。显示控件(例如按钮)是特定类型的事件源,并生成与其关联的事件类的对象。例如,单击按钮会发出 wx.CommandEvent。该事件数据被分派到程序中的事件处理程序方法。wxPython 有许多预定义的事件绑定器。事件绑定器封装了特定小部件(控件)、其关联事件类型和事件处理程序方法之间的关系。
例如,要在按钮的单击事件上调用程序的OnClick() 方法,需要以下语句 -
self.b1.Bind(EVT_BUTTON, OnClick)
所有显示对象都从 wx.EvtHandler 类继承Bind() 方法。这里的 EVT_.BUTTON 是绑定器,它将按钮单击事件关联到 OnClick() 方法。
例子
在下面的示例中,由拖动顶级窗口(在本例中为 wx.Frame 对象)引起的 MoveEvent 使用 wx.EVT_MOVE 绑定器连接到OnMove() 方法。该代码显示一个窗口。如果使用鼠标移动它,其瞬时坐标会显示在控制台上。
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()
上面的代码产生以下输出 -
当前窗口位置 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 | wxKey事件 按下或释放按键时发生 |
| 2 | wxPaintEvent 每当需要重绘窗口内容时生成 |
| 3 | wxMouseEvent 包含有关由鼠标活动(例如按下或拖动鼠标按钮)引起的任何事件的数据 |
| 4 | wxScrollEvent 与 wxScrollbar 和 wxSlider 等可滚动控件关联 |
| 5 | wxCommandEvent 包含源自许多小部件(例如按钮、对话框、剪贴板等)的事件数据。 |
| 6 | wx菜单事件 不同的菜单相关事件,不包括菜单命令按钮单击 |
| 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 类。上面的代码产生以下输出 -
Button received click event. Propagated to Panel class. Panel received click event. Propagated to Frame class. Click event received by frame class.