2013年2月7日 星期四

gtk中的事件處理--以evince為例

gtk的中文文件真的不多,而且很多己經過時,所以英文還是要練好一點…

在ev-view.c當中,宣告了 ev_view_button_press_event , 這個函數類似於在 win 平台上的 RAD 工具中的所謂“事件處理函式", 它會接收到一個型態為 GdkEventButton * 的參數,這裏面包含了事件的詳情。 此函數必需以某個方式讓事件處理迴圈知道, 程式中是以類別的virtual method table 中的 button_press_event 來存放。以Delphi/VCL的術語來說,widget就是VCL的control或window;在class的階層上,所有class都是由GObjectClass所衍生,類比於VCL的TObject,而所有視窗元件都是由GtkWidgetClass所衍生,類比於VCL的TWindow/TControl。

當事件發生時,捕捉這個事件並加以處理的途徑有兩個,分別是物件層級和類別層級。類別層級的處理由類別的(虛擬)函數進行,有效範圍是該類別的所有物件,若未進行override,則交由父類別處理,層層往上。 通常會去override這個函數的情況,一是對該類別的行為有一個統一要求,二是該類別只有一個實例(如主視窗),三是未來有可能會以該類別為父類別而衍生出新類別。其它的情況,處理事件時,物件層級優先於類別層級,適用於例如對話盒中的按鈕被按下後要有不同的行為,以override的方式則必需對各個按鈕寫出各自的類別,而改寫onclick函數(這名字是假設的);以event handler的方式則只需為不同的按鈕指定不同的onclick事件處理函數(這名字是假設的),比較簡單,gtk中是以g_signal_connect來指定。

不過物件層級的事件傳遞有自己的一條路徑,這是由 parent / child 所串起的一顆樹。與此相關的概念是建構/解構元件的從屬關係;通常視窗元件都是由主視窗所建,是一個 owner / component 的關係,只有記憶體管理的議題存在,沒有訊息的傳遞關係。VCL的設計是,放在可以拖放到視窗上的元件時,設立了TComponent類別來對應,處理一些warehousing的問題。

回到事件處理上,物件層級的處理,走完所有parent widgets都沒有辦法解決時,才會走parent classes這條,不過它的處理通常不會很針對不同的case,而是比較一般的通則。目前看到的情況也是如此,只有主視窗,雖然VCL中一貫使用物件層級處理,但是畢竟多了一層不必要的indirection,因此在gtk中似乎都傾向以類別層級來override VMT以進行事件處理。

沒有留言:

張貼留言