在wxpython中關於事件的名稱解釋:
- 事件(event):在你的應用程序期間發生的事情,它要求有一個響應。
- 事件對象(event object):在wxPython中,它具體代表一個事件,其中包括了事件的 數據等屬性。它是類wx.Event或其子類的實例,子類如wx.CommandEvent和 wx.MouseEvent。
- 事件類型(event type):wxPython分配給每個事件對象的一個整數ID。事件類型給出 了關於該事件本身更多的信息。例如,wx.MouseEvent的事件類型標識了該事件是 一個鼠標單擊還是一個鼠標移動。
- 事件源(event source):任何wxPython對象都能產生事件。例如按鈕、菜單、列表框 和任何別的窗口部件。
- 事件驅動(event driven):一個程序結構,它的大部分時間花在等待或響應事件上。
- 事件隊列(event queue):已發生的但未處理的事件的一個列表。
- 事件處理器(event handler):響應事件時所調用的函數或方法。也稱作處理器函數或 處理器方法。
- 事件綁定器(event binder):一個封裝了特定窗口部件,特定事件類型和一個事件處理器的wxPython對象。為了被調用,所有事件處理器必須用一個事件綁定器注冊。 wx.EvtHandler:一個wxPython類,它允許它的實例在一個特定類型,一個事件源, 和一個事件處理器之間創建綁定。注意,這個類與先前定義的事件處理函數或方法不 是同一個東西。
事件類
在wxPython中,代表事件的是事件對象。事件對象是類wx.Event或其子類的一個實例。
父類wx.Event相對小且抽象,它只是包含了對所有事件的一些通常的信息。wx.Event的各個子類都添加了更多的信息。
一個事件類可以有多個事件類型,每個都對應於一個不同的用 戶行為。
以下是wx.Event的重要的子類(事件類) :
- wx.CloseEvent:當一個框架關閉時觸發。這個事件的類型分為一個通常的框架關閉 和一個系統關閉事件。
- wx.KeyEvent::鍵盤事件, 例如當一個鍵被按下或釋放時發生。
- wx.PaintEvent:當窗口的內容需要被重畫時觸發。
- wx.MouseEvent:鼠標事件,如按下鼠標按鈕或拖動。
- wx.ScrollEvent 關聯像wxScrollbar和wxSlider滾動控制。
- wx.CommandEvent::與窗口部件的簡單的各種交互都將觸發這個事件,如按鈕單 擊、菜單項選擇、單選按鈕選擇。這些交互有它各自的事件類型。許多更復雜的窗口 部件,如列表等則定義wx.CommandEvent的子類。事件處理系統對待命令事件與其 它事件不同。
- wx.MenuEvent:不同的菜單相關的事件但不包括菜單命令按鈕點擊
- wx.ColourPickerEvent:wxColourPickerCtrl生成的事件。
- wx.DirFilePickerEvent:通過FileDialog和DirDialog生成的事件。
- wx.SizeEvent:當窗口的大小或其布局改變時觸發。
- wx.TimerEvent:可以由類wx.Timer類創建,它是定期的事件。
更多具體的事件類:官網文檔
事件綁定
事件綁定器被用於將一個wxPython窗口部件(事件源)與一個事件對象和一個處理器函數連接起來。
這個連接使得wxPython系統能夠通過執行處理器函數中的代碼 來響應相應窗口部件上的事件。
在wxPython中,任何能夠響應事件的對象都是 wx.EvtHandler的子類。
所有窗口對象都是wx.EvtHandler的子類,因些在wxPython應用程序中的每個窗口部件都能夠響應事件。
類wx.EvtHandler也能夠被非窗口部件對象所使用,如wx.App,因此事件處理功能不是限於可顯示的窗 口部件。
我們所說的窗口部件能響應事件的意思是:該窗口部件能夠創建事件綁定,在分派期間wxPython能夠識別該事件綁定。
由綁定器調用的在事件處理 器函數中的實際代碼不是必須位於一個wx.EvtHandler類中。
wx.EvtHandler有一個方法是Bind(),它創建事件綁定。該方法的用法如下:
Bind(event,handler,source=None,id=wx.ID_ANY,id2=wx.ID_ANY)
Bind()函數將一個事件和一個對象與一個事件處理器函數關聯起來。
- 參數 event是必選的,事件類型。
- 參數 handler也是必選的,它是一個可調用的Python對象,通常是一個被綁定的方法 或函數。處理器必須是可使用一個參數(事件對象本身)來調用的。
- 參數 handler可以是None,這種情況下,事件沒有關聯的處理器。
- 參數source是產生 該事件的源窗口部件,這個參數在觸發事件的窗口部件與用作事件處理器的窗口部件不相同時使用。
最常使用的wx.EvtHandler的方法:
- AddPendingEvent(event):將這個event參數放入事件處理系統中。類似於 ProcessEvent(),但它實際上不會立即觸發事件的處理。相反,該事件被增加到事件 隊列中。適用於線程間的基於事件的通信。
- Bind(event,handler,source=None,id=wx.ID_ANY,id2=wx.ID_ANY):事件綁定。
- GetEvtHandlerEnabled() SetEvtHandlerEnabled(boolean):如果處理器當前正在處理事件,則屬性為True, 否則為False。
- ProcessEvent(event):把event對象放入事件處理系統中以便立即處理。
事件驅動編程
從用戶的角度上來看,wxPython程序大部分時間什么也不做,一直閑着直 到用戶或系統做了些什么來觸發這個wxPython程序動作。
wxPython程序的結構 就是一個事件驅動程序體系的例子。
圖3.1是事件處理循環的示意,它展示了主程序的生命、用戶事件、和分派到的處理器函數。
事件驅動系統的主循環類似於客戶服務呼叫中心的操作者。當沒有呼叫的 進入的時候,這個操作者處於等待狀態。
當一個事件發生的時候,如電話鈴響了,這個操作者開始一個響應過程,他與客戶交談直到他獲得足夠的信息以分 派該客戶給一個合適的回答者。
然后操作者等待下一個事件。
盡管每個事件驅動系統之間有一些不同,但它們有很多相似的地方。下面列出了事件驅動程序結構的主要特點:
1、在初始化設置之后,程序的大部分時間花在了一個空閉的循環之中。 進入這個循環就標志着程序與用戶交互的部分的開始,退出這個循環就標志結束。在wxPython中,這個循環的方法是:wx.App.MainLoop(),並且在你的腳本 中顯式地被調用。當所有的頂級窗口關閉時,主循環退出。
2、程序包含了對應於發生在程序環境中的事情的事件。事件通常由用戶的行為觸發,但是也可以由系統的行為或程序中其他任意的代碼。在wxPython中,所有的事件都是類wx.Event或其子類的一個實例。每個事件都有一個事件 類型屬性,它使得不同的事件能夠被辨別。例如,鼠標釋放和鼠示按下事件都 被認為是同一個類的實例,但有不同的事件類型。
3、作為這個空閉的循環部分,程序定期檢查是否有任何請求響應事情發生。有兩種機制使得事件驅動系統可以得到有關事件的通知。最常被wxPython使用的方法是,把事件傳送到一個中心隊列,由該隊列觸發相應事件的處理。 另一種方法是使用輪詢的方法,所有可能引發事件的事件主被主過程定期查詢 並詢問是否有沒有處理的事件。
4、當事件發生時,基於事件的系統試着確定相關代碼來處理該事件,如果有,相關代碼被執行。在wxPython中,原系統事件被轉換為wx.Event實例, 然后使用wx.EvtHandler.ProcessEvent()方法將事件分派給適當的處理器代碼。圖 3.3呈現了這個過程:
事件機制的組成部分是事件綁定器對象和事件處理器。事件綁定器是一個 預定義的wxPython對象。每個事件都有各自的事件綁定器。事件處理器是一個函數或方法,它要求一個wxPython事件實例作為參數。當用戶觸發了適當的事件時,一個事件處理器被調用。
事件處理過程
事件處理過程開始於觸發事件的對象。通常,wxPython首先在觸發對象中查找匹配事件類型的被綁定的處理器函數。如果找到,則相應的方法被執行。
否則,wxPython將檢查該事件是否傳送到了上一級的容器。如果是的話,父窗口部件將被檢查,這樣一級一級向上尋找,直到wxPython找到了一個處理器函 數或到達了頂級窗口。
如果事件沒有傳播,在處理過程完成之前,wxPython仍將為了處理器函數而檢查應用程序對象。
第一步,創建事件
事件首先被交給創建事件的對象。對於按鈕敲擊,這個對象是按鈕;對於鼠標進入事件,這個對象是所進入的窗口部件。
第二步,確定事件對象是否被允許處理事件
通過調用wx.EvtHandler的SetEvtHandlerEnabled(boolean)方法,一個窗口可以被設置為允許或不允許事件處理。不允許事件處理的結果是該窗口部件在事 件處理中被完全繞過,與該對象關聯的綁定對象也不會被搜索,並且在這步中 的處理沒有向下的分支。
第三步 定位綁定器對象
然后ProcessEvent()方法尋找一個綁定器對象,該綁定器對象確定當前對象和事件類型之間的綁定。
如果對象自身的綁定器沒有被找到,那么向上到該對象的超類中去尋找。 如果一個綁定器對象被發現,wxPython調用相關的處理器函數。在處理器被調用后,該事件的事件處理停止,除非處理器函數顯式地要求作更多的處理
第四步 決定是否繼續處理
在調用了第一個事件處理器之后,wxPython查看是否有進一步的處理要 求。事件處理器通過調用wx.Event的方法Skip()要求更多的處理。如果Skip()方法被調用,那么處理將繼續,並且任何定義在超類中的處理器在這一步中被發現並執行。
第五步 決定是否展開
一個事件是否向上展開至容器級,這是每個事件實例的一個動態屬性,盡管實際上默認值幾乎總是使用那幾個。默認情況,只有wx.CommandEvent及其 子類的實例向上展開至容器級。其它的所有事件不這樣做。
總結
1、wxPython應用程序使用基於事件的控制流。應用程序的大部分時間花 費在一個主循環中,等待事件並分派它們到適當的處理器函數。
2、所有的wxPython事件類型是wx.Event類的子類,事件對象是這些類的實例。低級的事件,如鼠標敲擊, 被用來建立高級的事件,如按鈕敲擊或菜單項選擇。這些由wxPython窗口部件 引起的高級事件是類wx.CommandEvent的子類。大多的事件類通過一個事件類 型字段被進一步分類,事件類型字段區分事件。
3、為了捕獲事件和函數之間的關聯,wxPython使用類wx.PyEventBinder的 實例。類wx.PyEventBinder有許多預定義的實例,每個都對應於一個特定的事 件類型。每個wxPython窗口部件都是類wx.EvtHandler的子類。類wx.EvtHandler 有一個方法Bind(),它通常在初始化時被調用,所帶參數是一個事件綁定器實 例和一個處理器函數。根據事件的類型,別的wxPython對象的ID可能也需要被 傳遞給Bind()調用。
4、事件通常被發送給產生它們的對象,以搜索一個綁定對象,這個綁定 對象綁定事件到一個處理器函數。如果事件是命令事件,這個事件沿容器級向 上傳遞直到一個窗口部件被發現有一個針對該事件類型的處理器。一旦一個事 件處理器被發現,對於該事件的處理就停止,除非這個處理器調用了該事件的 Skip()方法。你可以允許多個處理器去響應一個事件,或去核查該事件的所有 默認行為。主循環的某些方面可以使用wx.App的方法來控制。
5、在wxPython中可以創建自定義事件,並作為定制(自定義)的窗口部 件的行為的一部分。自定義的事件是類wx.PyEvent的子類,自定義的命令事件 是類wx.PyCommandEvent的子類。為了創建一個自定義事件,新的類必須被定 義,並且關於每個事件類型(這些事件類型被這個新類所管理)的綁定器必須 被創建。最后,這個事件必須在系統的某處被生成,這通過經由ProcessEvent() 方法傳遞一個新的實例給事件處理器系統來實現。