天天看點

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 - 事件辨別符

請關注,評論,收藏,點贊,和轉發。