成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

移動開發
GTK Widget中內部結構與工作流程是本文要介紹的內容,主要是來了解并學習GTK Widget的流程,具體內容的實現來看本文詳解。

GTK Widget中內部結構與工作流程是本文要介紹的內容,主要是來了解并學習GTK Widget的流程,具體內容的實現來看本文詳解。

Gtk Widget的基本結構是這樣的:

  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轉的,只有有了window,Widget的存在才有意義。

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

一個Widget從創建、顯示到銷毀,大致要經過這么幾個過程:

1、創建(new)

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

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

創建之后就可以對widget進行各種屬性的設置了。

2、實例化(realize)

實例化的過程,就是將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

3、映射(map)

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

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

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

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

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

4、反映射(unmap)

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

5、反實例化(unrealize)

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

6、銷毀(destroy)

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

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

創建:

  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. /* 初始化函數,在g_object_new時自動調用 */  
  9. static void  
  10. gtk_entry_init (GtkEntry *entry)  
  11. {  
  12. GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);  
  13. /* 設置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. /* 設置拖放 */  
  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. /* 設置所城大小 */  
  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. /* 設置標志 */  
  6. GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);  
  7. /* …… */  
  8. /* 創建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. /* 調用父類的map函數,也就是GtkWidget的,這樣就不用自己設置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. /* 調用父類的unmap函數,也就是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. /* 調用父類的unrealize函數來銷毀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銷毀函數自動調用gobject來銷毀 */  
  6. GTK_OBJECT_CLASS (gtk_entry_parent_class)->destroy (object);  

小結:GTK Widget中內部結構與工作流程的內容介紹完了,希望通過GTK Widget內容的學習能對你有所幫助!

責任編輯:zhaolei 來源: 博客園
相關推薦

2020-05-12 23:20:50

Tomcat內部結構

2011-09-09 20:02:19

GTK Widget

2010-09-27 10:19:09

DHCP工作流程

2009-06-05 10:26:05

struts工作流程

2022-11-02 15:11:44

LightHouseChrome插件

2011-03-31 10:54:01

Cacti工作流程

2010-07-13 16:21:22

FIX協議

2010-07-28 17:19:28

ICMP協議

2010-06-24 16:40:16

Bittorrent協

2010-04-12 15:17:40

dump Oracle

2011-08-30 13:26:18

Mysql ProxyLua

2010-09-25 15:59:54

JVM虛擬機

2009-07-27 14:13:15

2011-03-29 09:30:12

Cacti

2010-06-12 17:44:19

ARP協議

2011-09-09 19:39:57

GTK Widget

2010-06-23 14:46:54

DHCP協議

2010-08-30 09:07:12

DHCP工作流程

2023-06-05 08:14:17

RabbitMQ兔子MQ開源

2009-08-07 11:10:40

Netbeans ID
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: wwwww在线观看| 夜夜骑首页 | 精品粉嫩aⅴ一区二区三区四区 | 伊人久久成人 | 欧美成人一区二区 | 国产精品99久久久精品免费观看 | 日本久久久久久 | 91麻豆精品国产91久久久更新资源速度超快 | av中文字幕网站 | 欧美大片黄 | 欧美成年网站 | 中文字幕一区二区三区不卡 | 国产欧美日韩视频 | 性一爱一乱一交一视频 | 成在线人视频免费视频 | 成人性生交大片免费看中文带字幕 | 国产一区中文 | 福利社午夜影院 | 一级全黄视频 | 国产精品免费一区二区三区四区 | 欧美激情精品久久久久 | 综合色久 | 国精产品一品二品国精在线观看 | 国产成人黄色 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 国内精品一区二区三区 | 亚洲色片网站 | 午夜精品久久久久久久星辰影院 | 天天爽天天操 | 国产一区二区在线看 | 日韩欧美亚洲 | 亚洲色视频 | 视频一区二区中文字幕 | 99精品视频一区二区三区 | 国产精品久久久久久久久久久久 | 红色av社区 | 中文字幕在线观看 | 伊人免费视频二 | 欧美一区永久视频免费观看 | 欧美日韩亚洲一区 | 国产精品久久久久久久久久久久午夜片 |