GTK Widget的內部結構與工作流程

2021-06-07 00:23:52 字數 3038 閱讀 5836

引用自:

gtkwidget的基本結構是這樣的:

typedef 

struct 

gtkwidget;

其中最重要的是它的window屬性,每個gtkwidget都必須有乙個window。widget是圍繞著window轉的,只有有了window,widget的存在才有意義。

要注意這裡的window是乙個gdkwindow,而不是gtkwindow。gdkwindow是對x的window的封裝,大致上是螢幕上的一塊矩形區域,可以在上面畫畫,可以接收事件。

乙個widget從建立、顯示到銷毀,大致要經過這麼幾個過程:

這是呼叫gtk_***_new時所觸發的。它幹的活很簡單,用gobject的物件系統建立乙個相應widget的例項。

當建立例項時,gobject會自動呼叫指定的初始化(init)函式(在get_type時指定),init函式負責把widget的各字段都初始化(把標題文字什麼的設為null之類的)。

注意此時window並沒有被建立,其實只是有了個widget的架子而已。

建立之後就可以對widget進行各種屬性的設定了。

例項化的過程,就是將window建立出來的過程。這其中包括幾個階段:

詢問大小請求(size_request)

gtk在例項化乙個widget之前,會詢問這個widget希望的大小是多大。widget可以根據自己的情況(例如屬性什麼的),計算出自己所需要的大小,也可以返回乙個預設值,反正就是widget自己定啦:)。

分配大小(size_allocate):

gtk獲得大小請求後就會給widget分配乙個大小。要注意的是分配的大小不一定和請求的大小相同。一般來說,在分配大小時widget需要做幾件事。

將分配的大小記錄在自己的allocation中。

如果自己的window已經建立了,那麼要改變自己所擁有的window的大小,使之符合所分配的大小。

如果widget是乙個容器(container),那麼對其所有的子widget也要相應地計算它們的大小並重新給它們分配大小。

分配大小可能發生在例項化之前,也可能在例項化後因為所屬容器的大小、位置發生變化而被重新分配,因此widget的window可能已經被建立,也可能是null,需要進行判斷。

例項化這才是真正的例項化階段。例項化所需要做的事只有乙個:用gdk_window_new建立window。建立好window後需要用gtk_widget_set_flags來給widget設定gtk_realized標誌。設定之後用gtk_realized巨集檢查widget是否已經被例項化時會返回true,表示該widget已經被例項化了。

可以用gtk_widget_realize手動例項化乙個widget

要注意的是map時需要判斷widget是否已經例項化(用gtk_realized),如果沒有,應該首先例項化widget,這樣才能顯示window。

同樣可以用gtk_widget_map手動對映乙個widget。

用gtk_widget_show來顯示乙個widget的本質,就是將widget例項化,並將其對映。當然每一步都要判斷是否已經做過,重複例項化和對映會造成資源洩漏(window被多次建立)和其他問題。

以上就是乙個widget從建立到顯示的過程。當然其中還有其父widget的流程。乙個widget當且僅當其父widget被例項化後才能例項化,對映亦然(放心,這個流程是gtk+自動判斷的)

接下來就是銷毀乙個widget時要做的事了。

銷毀乙個widget之前會自動要求將其反例項化。反例項化就是將window給銷毀(記得把window指標設回null),並取消(gtk_realized)標誌。

有時可能會需要用gtk_widget_unrealize來手動反例項化乙個widget。

和new對應,把剩下的資源釋放,最後用gobject的相應函式釋放整個widget

下面是取自gtkentry中的典型**:

建立:gtkwidget*

gtk_entry_new 

(void

)/* 初始化函式,在g_object_new時自動呼叫 */

static 

void

gtk_entry_init 

(gtkentry *entry

)大小分配:

static 

void

gtk_entry_size_allocate 

(gtkwidget     *widget,

gtkallocation *allocation

)}

大小請求:

static 

void

gtk_entry_size_request 

(gtkwidget      *widget,

gtkrequisition *requisition

)requisition->height = pango_pixels 

(entry->ascent + entry->descent

) + yborder * 

2 + inner_border.

top + inner_border.

bottom;

/* …… */

}

例項化:

static 

void

gtk_entry_realize 

(gtkwidget *widget

)對映:

static 

void

gtk_entry_map 

(gtkwidget *widget

)反映射:

static 

void

gtk_entry_unmap 

(gtkwidget *widget

)}

反例項化:

static 

void

gtk_entry_unrealize 

(gtkwidget *widget

)銷毀:

static 

void

gtk_entry_destroy 

(gtkobject *object

)

HBase內部結構

table表 就是有乙個或者多個列族組成,加上之前的 使用,這個表概念應該很熟了 row行 乙個行包括了多個列,這些列通過列族來分類 column family列族 列族是多個列的集合,hbase會盡量的將乙個列族的列放入同乙個伺服器內,這樣可以提高訪問效能,並且可以批量管理有關聯的一堆列,所有的資...

Oracle檢視內部結構

1 分析資料檔案塊,轉儲資料檔案n的塊m alter system dump datafile n block m 2 分析日誌檔案 alter system dump logfile logfilename 3 分析控制檔案的內容 alter session set events immediat...

MFC內部結構剖析

mfc內部結構剖析 mfc程式的執行順序依次是 程式在載入main函式之前,會先為全域性變數和全域性物件分配記憶體空間。afxwinmain函式 winmain函式實際上是通過呼叫afxwinmain函式來完成它的功能的。afxwinmain呼叫afxgetthread函式獲得乙個cwintread...