天天看点

wxPython - 系统常用事件

实战wxPython系列-014

wxPython - 系统常用事件

在wxPython中,包含了GUI应用所必须的一些常用事件,这些事件是构建一个GUI应用所必不可少的,比如绘制事件(wx.PaintEvent),焦点事件(wx.FocusEvent), 键盘事件(wx.KeyEvent),鼠标事件(wx.MouseEvent)等等。

一、绘制事件(wx.PaintEvent)

当窗口的内容需要重新绘制的时候,比如当我们调整窗口大小或者最大化的时候,会发送一个绘制事件(Paint Event)。当然我们也可以通过程序来触发绘制事件,比如,在调用Set Label()方法来修改wx.StaticText控件的文字信息时,就会触发绘制事件。注意,窗口最小化不会触发绘制事件。

wxPython - 系统常用事件

图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所示:

wxPython - 系统常用事件

图2:PaintEvent演示

二、焦点事件(wx.FocusEvent)

当窗口的焦点发生变化时,将发送焦点事件。焦点表明了当前应用中被选中的控件(widget),当控件被选中时,从键盘输入或从剪贴板拷入的文本将发送到该控件。又两个事件和焦点相关,它们是wx.EVT_SET_FOCUS和wx.EVT_KILL_FOCUS。当一个控件获得焦点时,就会触发wx.EVT_SET_FOCUS事件,当一个控件失去焦点时,则会触发wx.EVT_KILL_FOCUS事件。通过点击或者键盘按键比如Tab键或者Shift+Tab键可以在控件之间切换焦点。

wxPython - 系统常用事件

图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所示:

wxPython - 系统常用事件

图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键被按下时,退出整个应用。

wxPython - 系统常用事件

图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, 如果是,则弹出对话框,询问是否退出应用。

wxPython - 系统常用事件

图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将其转换为另一个窗口的窗口坐标。

wxPython - 系统常用事件

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

上面的例子我们演示了鼠标左键按下,鼠标左键释放,以及鼠标移动的情况,当鼠标左键按下或者释放时,在窗口中输出相应的信息,如果鼠标左键按下且移动,则在窗口中显示鼠标的位置信息。

wxPython - 系统常用事件

图8:MouseEvent演示

五、本文知识点

  • 了解绘制事件PaintEvent;
  • 了解焦点事件FocusEvent;
  • 了解键盘事件KeyEvent;
  • 了解鼠标事件MouseEvent。

前一篇:wxPython - 事件标识符

请关注,评论,收藏,点赞,和转发。