自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

GTK Widget中內(nèi)部結(jié)構(gòu)與工作流程

移動開發(fā)
GTK Widget中內(nèi)部結(jié)構(gòu)與工作流程是本文要介紹的內(nèi)容,主要是來了解并學習GTK Widget的流程,具體內(nèi)容的實現(xiàn)來看本文詳解。

GTK Widget中內(nèi)部結(jié)構(gòu)與工作流程是本文要介紹的內(nèi)容,主要是來了解并學習GTK Widget的流程,具體內(nèi)容的實現(xiàn)來看本文詳解。

Gtk Widget的基本結(jié)構(gòu)是這樣的:

  1. typedef struct {  
  2. GtkStyle *GSEAL (style);  
  3. GtkRequisition GSEAL (requisition);  
  4. GtkAllocation GSEAL (allocation);  
  5. GdkWindow *GSEAL (window);  
  6. GtkWidget *GSEAL (parent);  
  7. } GtkWidget 

;

其中最重要的是它的window屬性,每個GtkWidget都必須有一個window。Widget是圍繞著window轉(zhuǎn)的,只有有了window,Widget的存在才有意義。

要注意這里的window是一個GdkWindow,而不是GtkWindow。GdkWindow是對X的window的封裝,大致上是屏幕上的一塊矩形區(qū)域,可以在上面畫畫,可以接收事件。

一個Widget從創(chuàng)建、顯示到銷毀,大致要經(jīng)過這么幾個過程:

1、創(chuàng)建(new)

這是調(diào)用gtk_xxx_new時所觸發(fā)的。它干的活很簡單,用gobject的對象系統(tǒng)創(chuàng)建一個相應(yīng)widget的實例。
當創(chuàng)建實例時,gobject會自動調(diào)用指定的初始化(init)函數(shù)(在get_type時指定),init函數(shù)負責把widget的各字段都初始化(把標題文字什么的設(shè)為NULL之類的)。

注意此時window并沒有被創(chuàng)建,其實只是有了個widget的架子而已。

創(chuàng)建之后就可以對widget進行各種屬性的設(shè)置了。

2、實例化(realize)

實例化的過程,就是將window創(chuàng)建出來的過程。這其中包括幾個階段:

詢問大小請求(size_request)

GTK在實例化一個widget之前,會詢問這個widget希望的大小是多大。widget可以根據(jù)自己的情況(例如屬性什么的),計算出自己所需要的大小,也可以返回一個默認值,反正就是widget自己定啦:)。

分配大小(size_allocate):

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

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

如果自己的window已經(jīng)創(chuàng)建了,那么要改變自己所擁有的window的大小,使之符合所分配的大小。

如果widget是一個容器(container),那么對其所有的子widget也要相應(yīng)地計算它們的大小并重新給它們分配大小。

分配大小可能發(fā)生在實例化之前,也可能在實例化后因為所屬容器的大小、位置發(fā)生變化而被重新分配,因此widget的window可能已經(jīng)被創(chuàng)建,也可能是NULL,需要進行判斷。

實例化

這才是真正的實例化階段。實例化所需要做的事只有一個:用gdk_window_new創(chuàng)建window。創(chuàng)建好window后需要用 GTK_WIDGET_SET_FLAGS來給widget設(shè)置GTK_REALIZED標志。設(shè)置之后用GTK_REALIZED宏檢查widget是 否已經(jīng)被實例化時會返回TRUE,表示該widget已經(jīng)被實例化了。
可以用gtk_widget_realize手動實例化一個widget

3、映射(map)

所謂映射,就是將已經(jīng)創(chuàng)建好的window映射(顯示)到屏幕上。需要做的事是用gdk_window_show將window給顯示出來。和實例化時類似,需要用GTK_WIDGET_SET_FLAGS設(shè)置GTK_MAPPED標志,表示已經(jīng)映射好了。

要注意的是map時需要判斷widget是否已經(jīng)實例化(用GTK_REALIZED),如果沒有,應(yīng)該首先實例化widget,這樣才能顯示window。
同樣可以用gtk_widget_map手動映射一個widget。

用gtk_widget_show來顯示一個widget的本質(zhì),就是將widget實例化,并將其映射。當然每一步都要判斷是否已經(jīng)做過,重復(fù)實例化和映射會造成資源泄漏(window被多次創(chuàng)建)和其他問題。

以上就是一個widget從創(chuàng)建到顯示的過程。當然其中還有其父widget的流程。一個widget當且僅當其父widget被實例化后才能實例化,映射亦然(放心,這個流程是GTK+自動判斷的)

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

4、反映射(unmap)

當隱藏一個widget時,其實就是取消這個widget的映射。具體做法是用gtk_window_hide來隱藏window,并用GTK_WIDGET_UNSET_FLAGS來取消(GTK_MAPPED)。

5、反實例化(unrealize)

銷毀一個widget之前會自動要求將其反實例化。反實例化就是將window給銷毀(記得把window指針設(shè)回NULL),并取消(GTK_REALIZED)標志。
有時可能會需要用gtk_widget_unrealize來手動反實例化一個widget。

6、銷毀(destroy)

和new對應(yīng),把剩下的資源釋放,最后用gobject的相應(yīng)函數(shù)釋放整個widget

下面是取自GtkEntry中的典型代碼:

創(chuàng)建:

  1. GtkWidget*  
  2. gtk_entry_new (void)  
  3. {  
  4. /* 返回類型為GTK_TYPE_ENTRY的對象(Gobject的工作) */  
  5. return g_object_new (GTK_TYPE_ENTRY, NULL);  
  6. }  
  7.  
  8. /* 初始化函數(shù),在g_object_new時自動調(diào)用 */  
  9. static void  
  10. gtk_entry_init (GtkEntry *entry)  
  11. {  
  12. GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);  
  13. /* 設(shè)置widget標識 */  
  14. GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);  
  15. /* 初始化各字段 */  
  16. entry->text_size = MIN_SIZE;  
  17. entry->text = g_malloc (entry->text_size);  
  18. entry->text[0] = '\0';  
  19. /* …… */  
  20. /* 設(shè)置拖放 */  
  21. gtk_drag_dest_set (GTK_WIDGET (entry),  
  22. GTK_DEST_DEFAULT_HIGHLIGHT,  
  23. NULL, 0,  
  24. GDK_ACTION_COPY | GDK_ACTION_MOVE);  
  25. gtk_drag_dest_add_text_targets (GTK_WIDGET (entry));  
  26. /* 輸入法context */  
  27. entry->im_context = gtk_im_multicontext_new ();  
  28. /* 信號 */  
  29. g_signal_connect (entry->im_context, "commit",  
  30. G_CALLBACK (gtk_entry_commit_cb), entry);  
  31. /* …… */  

大小分配:

  1. static void  
  2. gtk_entry_size_allocate (GtkWidget     *widget,  
  3. GtkAllocation *allocation)  
  4. {  
  5. GtkEntry *entry = GTK_ENTRY (widget);  
  6. /* 保存到allocation中 */   
  7. widget->allocation = *allocation;  
  8. /* 判斷是否實例化 */  
  9. if (GTK_WIDGET_REALIZED (widget))  
  10. {  
  11. /* 計算窗口大小…… */  
  12. /* 改變窗口大小 */  
  13. gdk_window_move_resize (widget->window, x, y, width, height);  
  14. /* …… */  
  15. }  

大小請求:

  1. static void  
  2. gtk_entry_size_request (GtkWidget      *widget,  
  3. GtkRequisition *requisition)  
  4. {  
  5. /* 計算所需大小…… */  
  6. /* 設(shè)置所城大小 */  
  7. if (entry->width_chars < 0)  
  8. requisition->width = MIN_ENTRY_WIDTH + xborder * 2 + inner_border.left + inner_border.right;  
  9. else  
  10. {  
  11. /* …… */       
  12. requisition->width = char_pixels * entry->width_chars + xborder * 2 + inner_border.left + inner_border.right;  
  13. }  
  14. requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2 + inner_border.top + inner_border.bottom;  
  15. /* …… */  

實例化:

  1. static void  
  2. gtk_entry_realize (GtkWidget *widget)  
  3. {  
  4. /* …… */  
  5. /* 設(shè)置標志 */  
  6. GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);  
  7. /* …… */  
  8. /* 創(chuàng)建window */  
  9. widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);  
  10. gdk_window_set_user_data (widget->window, entry);  
  11. /* …… */  

映射:

  1. static void  
  2. gtk_entry_map (GtkWidget *widget)  
  3. {  
  4. /* …… */  
  5. /* 判斷是否可以且需要顯示 */  
  6. if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_MAPPED (widget))  
  7. {  
  8. /* 調(diào)用父類的map函數(shù),也就是GtkWidget的,這樣就不用自己設(shè)置GTK_MAPPED和顯示widget->window了 */  
  9. GTK_WIDGET_CLASS (gtk_entry_parent_class)->map (widget);  
  10. /* …… */  
  11. /* 顯示需要顯示的window */  
  12. gdk_window_show (icon_info->window);  
  13. /* …… */  

反映射:

  1. static void  
  2. gtk_entry_unmap (GtkWidget *widget)  
  3. {  
  4. /* …… */  
  5. /* 判斷是否需要隱藏 */  
  6. if (GTK_WIDGET_MAPPED (widget))  
  7. {  
  8. /* …… */  
  9. /* 隱藏需要顯示的window */  
  10. gdk_window_hide (icon_info->window);  
  11. /* …… */  
  12. /* 調(diào)用父類的unmap函數(shù),也就是GtkWidget的,這樣就不用自己取消GTK_MAPPED和隱藏widget->window了 */  
  13. GTK_WIDGET_CLASS (gtk_entry_parent_class)->unmap (widget);  
  14. }  

反實例化:

  1. static void  
  2. gtk_entry_unrealize (GtkWidget *widget)  
  3. {  
  4. /* …… */  
  5. /* 調(diào)用父類的unrealize函數(shù)來銷毀widget->window和取消GTK_REALIZED標識 */  
  6. GTK_WIDGET_CLASS (gtk_entry_parent_class)->unrealize (widget);  
  7. /* …… */  

銷毀:

  1. static void  
  2. gtk_entry_destroy (GtkObject *object)  
  3. {  
  4. /* 銷毀為成員分配的空間…… */  
  5. /* 用父類的object銷毀函數(shù)自動調(diào)用gobject來銷毀 */  
  6. GTK_OBJECT_CLASS (gtk_entry_parent_class)->destroy (object);  

小結(jié):GTK Widget中內(nèi)部結(jié)構(gòu)與工作流程的內(nèi)容介紹完了,希望通過GTK Widget內(nèi)容的學習能對你有所幫助!

責任編輯:zhaolei 來源: 博客園
相關(guān)推薦

2020-05-12 23:20:50

Tomcat內(nèi)部結(jié)構(gòu)

2011-09-09 20:02:19

GTK Widget

2009-06-05 10:26:05

struts工作流程

2010-09-27 10:19:09

DHCP工作流程

2022-11-02 15:11:44

LightHouseChrome插件

2011-03-31 10:54:01

Cacti工作流程

2010-04-12 15:17:40

dump Oracle

2010-09-25 15:59:54

JVM虛擬機

2011-08-30 13:26:18

Mysql ProxyLua

2010-06-24 16:40:16

Bittorrent協(xié)

2010-07-13 16:21:22

FIX協(xié)議

2010-07-28 17:19:28

ICMP協(xié)議

2010-06-12 17:44:19

ARP協(xié)議

2009-07-27 14:13:15

2011-03-29 09:30:12

Cacti

2011-09-09 19:39:57

GTK Widget

2010-06-23 14:46:54

DHCP協(xié)議

2010-08-30 09:07:12

DHCP工作流程

2009-08-07 11:10:40

Netbeans ID

2023-06-05 08:14:17

RabbitMQ兔子MQ開源
點贊
收藏

51CTO技術(shù)棧公眾號