GTK+ 2.0 教學-Hello World 詳解

現在我們知道基本理論了,讓我們來詳細分析helloworld範例程式。

這是按鈕被點擊時要呼叫的回呼函式。在這個範例中我們忽略了參數 widget 和 data,但是使用這些參數也不難。下一個範例會使用 data 參數來告訴我們哪個按鈕被按下了。

static void hello( GtkWidget *widget,
                   gpointer   data )
{
    g_print ("Hello Worldn");
}

接下來的一個回呼函式有點特殊。”delete_event” 在視窗管理員發送這個事件給應用程式時發生。我們在這裡可以選擇對這些事件做什麼。可以忽略它們,可以做一點回應,或是簡單地退出程式。
這個回呼函式傳回的值讓 GTK 知道該如何去做。傳回 TRUE,讓它知道我們不想讓 “destroy” 信號被發出,保持程式繼續執行。傳回 FALSE,我們讓 “destroy” 信號發出,這接著會呼叫 “destroy” 信號處理函式。

static gboolean delete_event( GtkWidget *widget,
                              GdkEvent  *event,
                              gpointer   data )
{
    g_print ("delete event occurredn");

    return TRUE;
}

這裡是另一個回呼函式,它通過呼叫 gtk_main_quit() 來退出程式。這個函式告訴 GTK 當控制權返回給它時就從 gtk_main 退出。

static void destroy( GtkWidget *widget,
                     gpointer   data )
{
    gtk_main_quit ();
}

我假設你知道 main() 函式…是的,像其它程式一樣,所有的 GTK 程式有一個 main() 函式。

int main( int   argc,
          char *argv[] )
{

接下來宣告兩個指向 GtkWidget 型別的結構指標。它們被用於建構一個視窗和一個按鈕。

GtkWidget *window;
GtkWidget *button;

這裡又是 gtk_init()。跟前面一樣,這個初始化工具包,分析命令列裡的參數。它從參數列表中刪除任何可以識別的參數,並且修改 argc 和 argv,使這些被刪除的參數好像從來就不存在一樣,而允許你的程式分析剩餘的參數。

gtk_init (&argc, &argv);

建構一個新視窗,這個很容易。它為 GtkWidget *window 結構分配了記憶體,這樣 window 現在指向了一個有效的結構。它建立了一個新視窗,但是這個視窗直到在程式後面部分我們呼叫 gtk_widget_show(window) 後才會顯示出來。

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

這有兩個連接一個信號處理器到一個物件 (本例中,就是 window ) 的範例。這裡,”delete_event” 和 “destroy” 信號被捕獲。當我們用視窗管理員去關閉視窗或呼叫函式 gtk_widget_destroy() 並將 window 元件作為物件傳給它來銷毀時,”delete_event” 信號發出。當我們在 “delete_event” 信號處理器中傳回 FALSE 值時,”destroy” 信號發出。G_CALLBACK 是巨集,可以為我們執行型別轉換和檢測,同時也增加了程式碼的可讀性。(註:舊版有G_OBJECT已不在範例中使用)

g_signal_connect (window, "delete-event",
                      G_CALLBACK (delete_event), NULL);
g_signal_connect (window, "destroy",
                      G_CALLBACK (destroy), NULL);

接下來這個函式用於設置容器物件的屬性。設置視窗邊框寬度為10個像素。在設置元件的屬性這一章還有其它類似函式。

再次,GTK_CONTAINER也是一個執行型別轉換的巨集。

gtk_container_set_border_width (GTK_CONTAINER (window), 10);

這個呼叫建構一個新按鈕。在記憶體中分配空間給一個新的 GtkWidget 結構,初始化它,並使 button 指標指向它。它顯示後上面會有個 “Hello World” 標籤。

button = gtk_button_new_with_label ("Hello World");

在 這,我們讓這個按鈕做一些有用的事。我們給按鈕設置信號處理器,因此當按鈕發出 “clicked” 信號時,hello() 函式被呼叫。我們忽略了 data 參數,簡單地傳送 NULL 給 hello() 回呼函式。很明顯地,當我們用滑鼠點擊按鈕時,信號 “clicked” 被發出。

g_signal_connect (button, "clicked",
                      G_CALLBACK (hello), NULL);
註:下面程式碼為舊版
g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), NULL);

我 們也要使用這個按鈕退出程式。這將說明 “destroy” 信號怎樣由視窗管理員引發,或由我們的程式引發。當按鈕被點擊(“clicked”)時,和上面一樣,它首先呼叫會 hello() 回呼函式,然後是這個函式,這依賴於它們被設置連接的順序。你可以擁有許多回呼函式,所有的回呼按你設置連接的順序依次執行。因為 gtk_widget_destroy() 函式只接受 GtkWidget *widget 作為唯一的參數,我們這裡用 g_signal_connect_swapped() 函式而不直接使用 g_signal_connect()。

g_signal_connect_swapped (button, "clicked",
                              G_CALLBACK (gtk_widget_destroy),
                              window);
註:下面程式碼為舊版
g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (gtk_widget_destroy), G_OBJECT (window));

這是一個封裝呼叫,在封裝元件這一章將作深入講解。不過它相當容易理解。它簡單地告訴 GTK 要把按鈕放在它顯示的視窗裡。注意一個 GTK 容器只能包含一個元件。還有其它的元件,在後面介紹,設計為用來以各種方法佈置多個元件。

gtk_container_add (GTK_CONTAINER (window), button);

一切準備就緒。所有信號處理器連接好了,按鈕也放進了視窗,我們讓 GTK 在螢幕上「顯示」這些元件。視窗元件最後顯示,這樣整個視窗會一下彈出,而不是先見到視窗彈出後再見到按鈕。雖然這個簡單的範例中,你不會注意到。

gtk_widget_show (button);

gtk_widget_show (window);

接著,當然,我們呼叫 gtk_main() 函式來等待來自 X 伺服器的事件,當這些事件到來時,呼叫元件發出信號。

gtk_main ();

最後傳回,呼叫函式gtk_main_quit() 後控制權傳回到這裡。

return 0;

現在,當我們用滑鼠點擊一個 GTK 按鈕,元件發出一個 “clicked” 信號。為了讓我們利用這個資訊,程式設置了一個信號處理器來捕獲那個信號,它按我們的選擇依次呼叫函式。在我們的範例中,當按下按鈕時,以 NULL 作為參數呼叫函式 hello(),然後呼叫該信號的下一個處理函式,該函式呼叫 gtk_widget_destroy() 函式,把視窗元件作為參數傳遞給它,銷毀視窗元件。這導致視窗發出 “destroy” 信號,它被捕獲,並且呼叫我們的 destroy() 回呼函式,簡單地退出 GTK。

如果用視窗管理員去關閉視窗,它會引發 “delete_event”。這會呼叫我們的 “delete_event” 處理函式。如果我們在函式中傳回 TRUE,視窗還是留在那裡,什麼事也不發生。傳回 FALSE,會使 GTK 發出 “destroy” 信號,它當然會呼叫 “destroy” 回呼,退出 GTK。

« 

單元首頁

感謝你看到這裡,很快就可以離開了,但最好的獎勵行動就是按一下幫我分享或留言,感恩喔~

點我分享到Facebook

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *