实战wxPython系列-014
在wxPython中,包含了GUI应用所必须的一些常用事件,这些事件是构建一个GUI应用所必不可少的,比如绘制事件(wx.PaintEvent),焦点事件(wx.FocusEvent), 键盘事件(wx.KeyEvent),鼠标事件(wx.MouseEvent)等等。
一、绘制事件(wx.PaintEvent)
当窗口的内容需要重新绘制的时候,比如当我们调整窗口大小或者最大化的时候,会发送一个绘制事件(Paint Event)。当然我们也可以通过程序来触发绘制事件,比如,在调用Set Label()方法来修改wx.StaticText控件的文字信息时,就会触发绘制事件。注意,窗口最小化不会触发绘制事件。
图1:wx.PaintEvent类继承关系
#绘制事件(wx.PaintEvent)
import wx
class SamplePaintEvent(wx.Frame):
def __init__(self, *args, **kw):
super(SamplePaintEvent, self).__init__(*args, **kw)
self.InitUi()
def InitUi(self):
self.count = 0
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("实战wxPython: 绘制事件")
self.SetSize(400, 280)
self.Centre()
def OnPaint(self, e):
self.count += 1
dc = wx.PaintDC(self)
text = "Number of paint events: {0}".format(self.count)
#从客户区指定像素点(20, 20)显示text
dc.DrawText(text, 20, 20)
def main():
app = wx.App()
sample = SamplePaintEvent(None)
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
在上面的例子中,我们对绘制事件进行计数,并在窗口中打印出计数值。该示例运行结果如图2所示:
图2:PaintEvent演示
二、焦点事件(wx.FocusEvent)
当窗口的焦点发生变化时,将发送焦点事件。焦点表明了当前应用中被选中的控件(widget),当控件被选中时,从键盘输入或从剪贴板拷入的文本将发送到该控件。又两个事件和焦点相关,它们是wx.EVT_SET_FOCUS和wx.EVT_KILL_FOCUS。当一个控件获得焦点时,就会触发wx.EVT_SET_FOCUS事件,当一个控件失去焦点时,则会触发wx.EVT_KILL_FOCUS事件。通过点击或者键盘按键比如Tab键或者Shift+Tab键可以在控件之间切换焦点。
图3:wx.FocusEvent类继承关系
#焦点事件(wx.FocusEvent)
import wx
class MyWindow(wx.Panel):
def __init__(self, parent):
super(MyWindow, self).__init__(parent)
#画笔颜色
self.color = "#b3b3b3"
#绑定事件处理
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
def OnPaint(self, e):
dc = wx.PaintDC(self)
# 设置画笔
dc.SetPen(wx.Pen(self.color))
# 获得客户区的尺寸
x,y = self.GetSize()
# 绘制一个矩形
dc.DrawRectangle(0, 0, x, y)
def OnSize(self, e):
#当客户区发生改变时,刷新客户区
self.Refresh()
def OnSetFocus(self, e):
#当进入焦点区域时,将画笔颜色设置为红色并重绘客户区
self.color = "#ff0000"
self.Refresh()
def OnKillFocus(self, e):
#当离开焦点区域时,将画笔颜色恢复为初始颜色并重绘客户区
self.color = "#b3b3b3"
self.Refresh()
class SampleFocusEvent(wx.Frame):
def __init__(self, *args, **kw):
super(SampleFocusEvent, self).__init__(*args, **kw)
self.InitUi()
def InitUi(self):
#创建一个2x2网格布局
grid = wx.GridSizer(2, 2, 10, 10)
grid.AddMany([(MyWindow(self), 0, wx.EXPAND|wx.TOP|wx.LEFT, 9),
(MyWindow(self), 0, wx.EXPAND|wx.TOP|wx.RIGHT, 9),
(MyWindow(self), 0, wx.EXPAND|wx.BOTTOM|wx.LEFT, 9),
(MyWindow(self), 0, wx.EXPAND|wx.BOTTOM|wx.RIGHT, 9)])
self.SetSizer(grid)
self.SetSize(400, 280)
self.SetTitle("实战wxPython: 焦点事件")
self.Centre()
def main():
app = wx.App()
sample = SampleFocusEvent(None)
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
在上面的例子中,创建了4个panel,获得焦点的panel被高亮显示。
self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
上面的代码把两个焦点事件绑定到事件处理函数。
在panel获得焦点时,在OnPaint()方法中将绘制一个红色的边框。上面的例子运行效果如图4所示:
图4:FocusEvent演示
三、键盘事件(wx.KeyEvent)
键盘事件类包含有关按键和释放事件的信息。
键盘事件所携带的主要信息是正在按下或释放的键。它可以使用GetUnicodeKey, GetKeyCode或GetRawKeyCode函数之一来访问。对于可打印字符,应该使用GetUnicodeKey,因为它适用于任何键,包括使用国家键盘布局时可以输入的非latin -1字符。GetKeyCode应该用于处理与wx对应的特殊字符(如光标箭头键或HOME或INS等)。
虽然因为兼容性要求,GetKeyCode还返回Latin-1键的字符代码,但它一般不适用于Unicode字符,并且对于任何非Latin-1键将返回WXK_NONE。如果GetUnicodeKey和GetKeyCode都返回WXK_NONE,那么该键没有WXK_xxx映射,GetRawKeyCode可以用来区分键,但原始键代码是特定于平台上的。出于这些原因,建议总是使用GetUnicodeKey,只有当GetUnicodeKey返回WXK_NONE时才返回GetKeyCode,这意味着该事件对应于一个不可打印的特殊键,如果GetKeyCode也返回WXK_NONE,则可考虑检查GetRawKeyCode,或者直接忽略该键。
当我们在键盘上按下按钮时,一个 wx.KeyEvent 会被触发并被发送到当前焦点控件。有三种不同的键盘事件:
- wx.EVT_KEY_DOWN
- wx.EVT_KEY_UP
- wx.EVT_CHAR
一个常用的应用需求是,当Esc键被按下时,退出整个应用。
图5:wx.KeyEvent类继承关系
#键盘事件(wx.FocusEvent)
import wx
class SampleKeyEvent(wx.Frame):
def __init__(self, *args, **kw):
super(SampleKeyEvent, self).__init__(*args, **kw)
self.InitUi()
def InitUi(self):
panel = wx.Panel(self)
panel.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
panel.SetFocus()
self.SetSize(400, 280)
self.SetTitle("实战wxPython: 键盘事件")
self.Centre()
def OnKeyDown(self, e):
key = e.GetKeyCode()
if key == wx.WXK_ESCAPE:
ret = wx.MessageBox("确定要退出应用?", "问题", wx.YES_NO|wx.NO_DEFAULT, self)
if ret == wx.YES:
self.Close()
def main():
app = wx.App()
sample = SampleKeyEvent(None)
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
在这个例子中,我们处理了Esc键按下事件,当按下Esc键时,会弹出一个对话框,询问是否关闭应用。
panel.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
上面代码将EVT_KEY_DOWN事件绑定至self.OnKeyDown()方法。在OnKeyDown方法中,通过
key = e.GetKeyCode()
获得按键值,然后检查按键值是否为wx.WXK_EACAPE, 如果是,则弹出对话框,询问是否退出应用。
图6:KeyEvent演示
四、鼠标事件(wx.KeyEvent)
鼠标事件类包含关于鼠标生成的事件的信息:它们包括鼠标按钮按下并释放事件和鼠标移动事件。
所有涉及按钮的鼠标事件都使用MOUSE_BTN_LEFT作为鼠标左键,MOUSE_BTN_MIDDLE作为中间键,MOUSE_BTN_RIGHT作为右边键。如果系统支持更多按钮,还可以生成MOUSE_BTN_AUX1和MOUSE_BTN_AUX2事件。注意,并不是所有的鼠标都有一个中间按钮,所以便携式应用程序应该避免依赖于它的事件(但是在Mac平台下,可以使用鼠标左键和控制键来模拟单击右键)。
注意:对于wxEVT_ENTER_WINDOW和wxEVT_LEAVE_WINDOW事件的目的,如果鼠标在窗口客户端区域中,而不在它的一个子窗口中,则认为鼠标在窗口内。换句话说,父窗口不仅在鼠标完全离开窗口时接收wxEVT_LEAVE_WINDOW事件,而且在鼠标进入其中一个子窗口时也接收wxEVT_LEAVE_WINDOW事件。
与鼠标事件相关的位置用生成事件窗口的窗口坐标表示,我们可以使用wx.Window.ClientToScreen将其转换为屏幕坐标,也可以调用wx.Window.ScreenToClient将其转换为另一个窗口的窗口坐标。
图7:wx.MouseEvent类继承关系
#鼠标事件(wx.MouseEvent)
import wx
class SampleMouseEvent(wx.Frame):
def __init__(self, *args, **kw):
super(SampleMouseEvent, self).__init__(*args, **kw)
self.info = ""
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.SetTitle("实战wxPython: 鼠标事件")
self.SetSize(400, 280)
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.DrawText(self.info, 20, 20)
def OnLeftDown(self, e):
self.info = "Mouse left button is pressed"
self.Refresh();
def OnLeftUp(self, e):
self.info = "Mouse left button is released"
self.Refresh()
def OnMouseMove(self, e):
#如果按下左键并移动鼠标,则显示当前鼠标的坐标信息
if e.Dragging() and e.LeftIsDown():
x,y = e.GetPosition()
self.info = "current pos: x=" + str(x) + ", y=" + str(y)
self.Refresh()
def main():
app = wx.App()
sample = SampleMouseEvent(None)
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
上面的例子我们演示了鼠标左键按下,鼠标左键释放,以及鼠标移动的情况,当鼠标左键按下或者释放时,在窗口中输出相应的信息,如果鼠标左键按下且移动,则在窗口中显示鼠标的位置信息。
图8:MouseEvent演示
五、本文知识点
- 了解绘制事件PaintEvent;
- 了解焦点事件FocusEvent;
- 了解键盘事件KeyEvent;
- 了解鼠标事件MouseEvent。
前一篇:wxPython - 事件标识符
请关注,评论,收藏,点赞,和转发。