實戰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 - 事件辨別符
請關注,評論,收藏,點贊,和轉發。