GTK環境搭建( Linux )
安裝命令
sudo apt-get install libgtk3.0*
lin@lin-host:~$ sudo apt-get install libgtk3.0* [sudo] password for lin: Reading package lists... Done Building dependency tree Reading state information... Done
測試是否安裝成功
pkg-config --cflags --libs gtk+-3.0
lin@lin-host:~$ pkg-config --cflags --libs gtk+-3.0 -pthread -I/usr/include/gtk-3.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/pixman-1 -I/usr/include/libpng12 -lgtk-3 -lgdk-3 -latk-1.0 -lgio-2.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo-gobject -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0
現在我們建立簡單的一個空白窗口
代碼如下
#include <gtk/gtk.h> int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 最后一步是顯示新創建的窗口 */ gtk_widget_show (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
編譯方法
$ gcc main.c `pkg-config --libs --cflags gtk+-3.0`
【備注】這邊`是按鍵ESC下的
或者寫一個腳本
#!/bin/bash gcc $1 `pkg-config --libs --cflags gtk+-3.0`
給記得給腳本 chmod +x
執行腳本。、
$ ./cmd.sh main.c
測試一下我們編譯的
$ ./a.out
現在我們修改標題欄
新增代碼如下紅色所示
int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 最后一步是顯示新創建的窗口 */ gtk_widget_show (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
現在我們添加按鍵

#include <gtk/gtk.h> int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (window), button); /* 最后一步是顯示新創建的按鈕*/ gtk_widget_show (button); /* 最后一步是顯示新創建的窗口 */ gtk_widget_show (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
現在我們在按鍵點擊輸出一些信息
#include <gtk/gtk.h> /* 這是一個回調函數*/ void hello( GtkWidget *widget, gpointer data ) { g_print ("Hello World %s\n",(gchar *) data); } int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 設置窗口邊框的寬度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "GTK"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (window), button); /* 最后一步是顯示新創建的按鈕*/ gtk_widget_show (button); /* 最后一步是顯示新創建的窗口 */ gtk_widget_show (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
現在我們增加關閉窗口提示信息
#include <gtk/gtk.h> /* 這是一個回調函數*/ void hello( GtkWidget *widget, gpointer data ) { g_print ("Hello World %s\n",(gchar *) data); } gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* 如果你的 "delete_event" 信號處理函數返回 FALSE,GTK 會發出 "destroy" 信號。 * 返回 TRUE,你不希望關閉窗口。 * 當你想彈出“你確定要退出嗎?”對話框時它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 為 FALSE 程序會關閉。*/ return FALSE; } /* 一個回調函數 */ void destroy( GtkWidget *widget, gpointer data ) { g_print ("destroy event \n"); gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 當窗口收到 "delete_event" 信號 (這個信號由窗口管理器發出,通常是“關閉” * 選項或是標題欄上的關閉按鈕發出的),我們讓它調用在前面定義的 delete_event() 函數。 * 傳給回調函數的 data 參數值是 NULL,它會被回調函數忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); /* 在這里我們連接 "destroy" 事件到一個信號處理函數。 * 對這個窗口調用 gtk_widget_destroy() 函數或在 "delete_event" 回調函數中返回 FALSE 值 * 都會觸發這個事件。*/ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); /* 設置窗口邊框的寬度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* 創建一個標簽為 "Hello World" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "GTK"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (window), button); /* 最后一步是顯示新創建的按鈕*/ gtk_widget_show (button); /* 最后一步是顯示新創建的窗口 */ gtk_widget_show (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
現在我們該為按鍵來控制關閉
#include <gtk/gtk.h> /* 這是一個回調函數*/ void hello( GtkWidget *widget, gpointer data ) { g_print ("Hello World %s\n",(gchar *) data); } gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* 如果你的 "delete_event" 信號處理函數返回 FALSE,GTK 會發出 "destroy" 信號。 * 返回 TRUE,你不希望關閉窗口。 * 當你想彈出“你確定要退出嗎?”對話框時它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 為 FALSE 程序會關閉。*/ return FALSE; } /* 一個回調函數 */ void destroy( GtkWidget *widget, gpointer data ) { g_print ("destroy event \n"); gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 當窗口收到 "delete_event" 信號 (這個信號由窗口管理器發出,通常是“關閉” * 選項或是標題欄上的關閉按鈕發出的),我們讓它調用在前面定義的 delete_event() 函數。 * 傳給回調函數的 data 參數值是 NULL,它會被回調函數忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); /* 在這里我們連接 "destroy" 事件到一個信號處理函數。 * 對這個窗口調用 gtk_widget_destroy() 函數或在 "delete_event" 回調函數中返回 FALSE 值 * 都會觸發這個事件。*/ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); /* 設置窗口邊框的寬度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* 創建一個標簽為 "Hello World" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); #if 0 /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "GTK"); #else /* 當點擊按鈕時,會通過調用 gtk_widget_destroy(window) 來關閉窗口。 * "destroy" 信號會從這里或從窗口管理器發出。*/ g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (gtk_widget_destroy),window); #endif /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (window), button); /* 最后一步是顯示新創建的按鈕*/ gtk_widget_show (button); /* 最后一步是顯示新創建的窗口 */ gtk_widget_show (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
我們新增兩個按鍵
#include <gtk/gtk.h> /* 這是一個回調函數*/ void hello( GtkWidget *widget, gpointer data ) { g_print ("Hello World %s\n",(gchar *) data); } gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* 如果你的 "delete_event" 信號處理函數返回 FALSE,GTK 會發出 "destroy" 信號。 * 返回 TRUE,你不希望關閉窗口。 * 當你想彈出“你確定要退出嗎?”對話框時它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 為 FALSE 程序會關閉。*/ return FALSE; } /* 一個回調函數 */ void destroy( GtkWidget *widget, gpointer data ) { g_print ("destroy event \n"); gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; GtkWidget *box1; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 當窗口收到 "delete_event" 信號 (這個信號由窗口管理器發出,通常是“關閉” * 選項或是標題欄上的關閉按鈕發出的),我們讓它調用在前面定義的 delete_event() 函數。 * 傳給回調函數的 data 參數值是 NULL,它會被回調函數忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); /* 在這里我們連接 "destroy" 事件到一個信號處理函數。 * 對這個窗口調用 gtk_widget_destroy() 函數或在 "delete_event" 回調函數中返回 FALSE 值 * 都會觸發這個事件。*/ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); /* 設置窗口邊框的寬度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* 我們創建了一個組裝盒。詳情參見“組裝”章節。我們看不見組裝盒,它僅被作為排列構件的工具。*/ #if 0 box1 = gtk_hbox_new (FALSE, 1); //GTK2.0支持 #else box1 =gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);//GTK3.0推薦 #endif /* 把組裝盒放入主窗口中。*/ gtk_container_add (GTK_CONTAINER (window), box1); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "1"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "2"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "3"); #if 0 /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); #else /* 代替 gtk_container_add,我們把按鈕放入不可見的組裝盒,該組合盒已經組裝進窗口中了。*/ gtk_box_pack_start (GTK_BOX(box1), button, TRUE, TRUE, 0); #endif
/* 顯示新創建的按鈕*/ gtk_widget_show (button); gtk_widget_show (box1); /* 最后一步是顯示新創建的窗口 */ gtk_widget_show (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
現在我們增加label來顯示按鍵的信息
將使用到的函數
GtkWidget *gtk_label_new (const gchar *str); void gtk_label_set_text (GtkLabel *label,const gchar *str);
代碼如下

#include <gtk/gtk.h> /*聲明全局變量label*/ GtkWidget *label; /* 這是一個回調函數*/ void hello( GtkWidget *widget, gpointer data ) { g_print ("Hello World %s\n",(gchar *) data); gtk_label_set_text (GTK_LABEL(label),(gchar *) data); } gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* 如果你的 "delete_event" 信號處理函數返回 FALSE,GTK 會發出 "destroy" 信號。 * 返回 TRUE,你不希望關閉窗口。 * 當你想彈出“你確定要退出嗎?”對話框時它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 為 FALSE 程序會關閉。*/ return FALSE; } /* 一個回調函數 */ void destroy( GtkWidget *widget, gpointer data ) { g_print ("destroy event \n"); gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; GtkWidget *box1; GtkWidget *box2; GtkWidget *box3; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 當窗口收到 "delete_event" 信號 (這個信號由窗口管理器發出,通常是“關閉” * 選項或是標題欄上的關閉按鈕發出的),我們讓它調用在前面定義的 delete_event() 函數。 * 傳給回調函數的 data 參數值是 NULL,它會被回調函數忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); /* 在這里我們連接 "destroy" 事件到一個信號處理函數。 * 對這個窗口調用 gtk_widget_destroy() 函數或在 "delete_event" 回調函數中返回 FALSE 值 * 都會觸發這個事件。*/ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); /* 設置窗口邊框的寬度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* 我們創建了一個組裝盒。詳情參見“組裝”章節。我們看不見組裝盒,它僅被作為排列構件的工具。*/ box1 =gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);//GTK3.0 box2 =gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); box3 =gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); /* 把組裝盒放入主窗口中。*/ gtk_container_add (GTK_CONTAINER (window), box3); gtk_container_add (GTK_CONTAINER (box3), box1); gtk_container_add (GTK_CONTAINER (box3), box2); /*創建標簽*/ label = gtk_label_new("label"); /*布局容器里*/ gtk_container_add(GTK_CONTAINER(box2), label); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "1"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "2"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "3"); /* 代替 gtk_container_add,我們把按鈕放入不可見的組裝盒,該組合盒已經組裝進窗口中了。*/ gtk_box_pack_start (GTK_BOX(box1), button, TRUE, TRUE, 0); /* 顯示 */ gtk_widget_show_all (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
我們現在在原來基礎上使用g_string_printf
GString *g_string_new (const gchar *init); void g_string_printf (GString *string, const gchar *format, ...);
gchar *g_string_free (GString *string,
gboolean free_segment);
代碼如下

#include <gtk/gtk.h> /*聲明全局變量label*/ GtkWidget *label; /* 這是一個回調函數*/ void hello( GtkWidget *widget, gpointer data ) { GString *string=g_string_new (NULL); g_print ("Hello World %s\n",(gchar *) data); g_string_printf(string,"Hello World %s\n", (gchar *) data); gtk_label_set_text (GTK_LABEL(label),string->str); g_string_free(string, TRUE); } gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* 如果你的 "delete_event" 信號處理函數返回 FALSE,GTK 會發出 "destroy" 信號。 * 返回 TRUE,你不希望關閉窗口。 * 當你想彈出“你確定要退出嗎?”對話框時它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 為 FALSE 程序會關閉。*/ return FALSE; } /* 一個回調函數 */ void destroy( GtkWidget *widget, gpointer data ) { g_print ("destroy event \n"); gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; GtkWidget *box1; GtkWidget *box2; GtkWidget *box3; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 當窗口收到 "delete_event" 信號 (這個信號由窗口管理器發出,通常是“關閉” * 選項或是標題欄上的關閉按鈕發出的),我們讓它調用在前面定義的 delete_event() 函數。 * 傳給回調函數的 data 參數值是 NULL,它會被回調函數忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); /* 在這里我們連接 "destroy" 事件到一個信號處理函數。 * 對這個窗口調用 gtk_widget_destroy() 函數或在 "delete_event" 回調函數中返回 FALSE 值 * 都會觸發這個事件。*/ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); /* 設置窗口邊框的寬度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* 我們創建了一個組裝盒。詳情參見“組裝”章節。我們看不見組裝盒,它僅被作為排列構件的工具。*/ box1 =gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);//GTK3.0 box2 =gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); box3 =gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); /* 把組裝盒放入主窗口中。*/ gtk_container_add (GTK_CONTAINER (window), box3); gtk_container_add (GTK_CONTAINER (box3), box1); gtk_container_add (GTK_CONTAINER (box3), box2); /*創建標簽*/ label = gtk_label_new("label"); /*布局容器里*/ gtk_container_add(GTK_CONTAINER(box2), label); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "1"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "2"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "3"); /* 代替 gtk_container_add,我們把按鈕放入不可見的組裝盒,該組合盒已經組裝進窗口中了。*/ gtk_box_pack_start (GTK_BOX(box1), button, TRUE, TRUE, 0); /* 顯示 */ gtk_widget_show_all (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
現在添加鼠標事件
void gtk_widget_add_events (GtkWidget *widget, gint events);
代碼如下

#include <gtk/gtk.h> /*聲明全局變量label*/ GtkWidget *label; /* 這是一個回調函數*/ void hello( GtkWidget *widget, gpointer data ) { GString *string=g_string_new (NULL); g_print ("Hello World %s\n",(gchar *) data); g_string_printf(string,"Hello World %s\n", (gchar *) data); gtk_label_set_text (GTK_LABEL(label),string->str); g_string_free(string, TRUE); } gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* 如果你的 "delete_event" 信號處理函數返回 FALSE,GTK 會發出 "destroy" 信號。 * 返回 TRUE,你不希望關閉窗口。 * 當你想彈出“你確定要退出嗎?”對話框時它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 為 FALSE 程序會關閉。*/ return FALSE; } /* 一個回調函數 */ void destroy( GtkWidget *widget, gpointer data ) { g_print ("destroy event \n"); gtk_main_quit (); } // 鼠標點擊事件處理函數 gboolean deal_mouse_press(GtkWidget *widget, GdkEventButton *event, gpointer data) { switch(event->button){ // 判斷鼠標點擊的類型 case 1: g_print ("Left Button!!\n"); break; case 2: g_print ("Middle Button!!\n"); break; case 3: g_print ("Right Button!!\n"); break; default: g_print ("Unknown Button!!\n"); } if(event->type == GDK_2BUTTON_PRESS){ g_print ("double click\n"); } // 獲得點擊的坐標值,距離窗口左頂點 gint i = event->x; gint j = event->y; g_print ("press_x = %d, press_y = %d\n", i, j); return TRUE; } // 鼠標移動事件(點擊鼠標任何鍵)的處理函數 gboolean deal_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) { // 獲得移動鼠標的坐標值,距離窗口左頂點 gint i = event->x; gint j = event->y; g_print ("motion_x = %d, motion_y = %d\n", i, j); return TRUE; } int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; GtkWidget *box1; GtkWidget *box2; GtkWidget *box3; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 當窗口收到 "delete_event" 信號 (這個信號由窗口管理器發出,通常是“關閉” * 選項或是標題欄上的關閉按鈕發出的),我們讓它調用在前面定義的 delete_event() 函數。 * 傳給回調函數的 data 參數值是 NULL,它會被回調函數忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); /* 在這里我們連接 "destroy" 事件到一個信號處理函數。 * 對這個窗口調用 gtk_widget_destroy() 函數或在 "delete_event" 回調函數中返回 FALSE 值 * 都會觸發這個事件。*/ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); /* 設置窗口邊框的寬度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* 我們創建了一個組裝盒。詳情參見“組裝”章節。我們看不見組裝盒,它僅被作為排列構件的工具。*/ box1 =gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);//GTK3.0 box2 =gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); box3 =gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); /* 把組裝盒放入主窗口中。*/ gtk_container_add (GTK_CONTAINER (window), box3); gtk_container_add (GTK_CONTAINER (box3), box1); gtk_container_add (GTK_CONTAINER (box3), box2); /*創建標簽*/ label = gtk_label_new("label"); /*布局容器里*/ gtk_container_add(GTK_CONTAINER(box2), label); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "1"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "2"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_container_add (GTK_CONTAINER (box1), button); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "3"); /* 代替 gtk_container_add,我們把按鈕放入不可見的組裝盒,該組合盒已經組裝進窗口中了。*/ gtk_box_pack_start (GTK_BOX(box1), button, TRUE, TRUE, 0); /*窗口接收鼠標事件*/ // GDK_BUTTON_PRESS_MASK:鼠標點擊事件 // GDK_BUTTON_MOTION_MASK:按住鼠標移動事件 gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK); // "button-press-event" 與 deal_mouse_event 連接,鼠標點擊事件 g_signal_connect(window, "button-press-event", G_CALLBACK(deal_mouse_press), NULL); // "motion-notify-event" 與 deal_motion_notify_event 連接,按住鼠標移動事件 g_signal_connect(window, "motion-notify-event", G_CALLBACK(deal_motion_notify_event), NULL); /* 顯示 */ gtk_widget_show_all (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }
【知識點】關於GTK的信號量和事件可以參考https://www.cnblogs.com/tianshuai11/archive/2012/01/05/2477206.html
使用grid的來布局
主要函數
GtkWidget *gtk_grid_new (void); void gtk_grid_attach (GtkGrid *grid, GtkWidget *child, gint left, gint top, gint width, gint height);
代碼如下

#include <gtk/gtk.h> /*聲明全局變量label*/ GtkWidget *label; /* 這是一個回調函數*/ void hello( GtkWidget *widget, gpointer data ) { GString *string=g_string_new (NULL); g_print ("Hello World %s\n",(gchar *) data); g_string_printf(string,"Hello World %s\n", (gchar *) data); gtk_label_set_text (GTK_LABEL(label),string->str); g_string_free(string, TRUE); } gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* 如果你的 "delete_event" 信號處理函數返回 FALSE,GTK 會發出 "destroy" 信號。 * 返回 TRUE,你不希望關閉窗口。 * 當你想彈出“你確定要退出嗎?”對話框時它很有用。*/ g_print ("delete event occurred\n"); /* 改 TRUE 為 FALSE 程序會關閉。*/ return FALSE; } /* 一個回調函數 */ void destroy( GtkWidget *widget, gpointer data ) { g_print ("destroy event \n"); gtk_main_quit (); } // 鼠標點擊事件處理函數 gboolean deal_mouse_press(GtkWidget *widget, GdkEventButton *event, gpointer data) { switch(event->button){ // 判斷鼠標點擊的類型 case 1: g_print ("Left Button!!\n"); break; case 2: g_print ("Middle Button!!\n"); break; case 3: g_print ("Right Button!!\n"); break; default: g_print ("Unknown Button!!\n"); } if(event->type == GDK_2BUTTON_PRESS){ g_print ("double click\n"); } // 獲得點擊的坐標值,距離窗口左頂點 gint i = event->x; gint j = event->y; g_print ("press_x = %d, press_y = %d\n", i, j); return TRUE; } // 鼠標移動事件(點擊鼠標任何鍵)的處理函數 gboolean deal_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) { // 獲得移動鼠標的坐標值,距離窗口左頂點 gint i = event->x; gint j = event->y; g_print ("motion_x = %d, motion_y = %d\n", i, j); return TRUE; } int main( int argc, char *argv[] ) { /* GtkWidget 是構件的存儲類型 */ GtkWidget *window; GtkWidget *button; GtkWidget *box1; GtkWidget *box2; GtkWidget *box3; GtkWidget *grid; /* 這個函數在所有的 GTK 程序都要調用。參數由命令行中解析出來並且送到該程序中*/ gtk_init (&argc, &argv); /* 創建一個新窗口 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 設置title文字,注意UTF8格式的文字轉換,否則是亂碼*/ gtk_window_set_title(GTK_WINDOW (window), g_locale_to_utf8("你好",-1,NULL,NULL,NULL)); /* 當窗口收到 "delete_event" 信號 (這個信號由窗口管理器發出,通常是“關閉” * 選項或是標題欄上的關閉按鈕發出的),我們讓它調用在前面定義的 delete_event() 函數。 * 傳給回調函數的 data 參數值是 NULL,它會被回調函數忽略。*/ g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); /* 在這里我們連接 "destroy" 事件到一個信號處理函數。 * 對這個窗口調用 gtk_widget_destroy() 函數或在 "delete_event" 回調函數中返回 FALSE 值 * 都會觸發這個事件。*/ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); /* 設置窗口邊框的寬度。*/ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* 我們創建了一個組裝盒。詳情參見“組裝”章節。我們看不見組裝盒,它僅被作為排列構件的工具。*/ grid = gtk_grid_new (); /* 把組裝盒放入主窗口中。*/ gtk_container_add (GTK_CONTAINER (window), grid); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "1"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "2"); /* 把按鈕放入窗口 (一個 gtk 容器) 中。*/ gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1); /* 顯示新創建的按鈕*/ gtk_widget_show (button); /* 創建一個標簽為 "button" 的新按鈕。*/ button = gtk_button_new_with_label ("button"); /* 當按鈕收到 "clicked" 信號時會調用 hello() 函數,並將NULL傳給 * 它作為參數。hello() 函數在前面定義了。*/ g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), "3"); gtk_grid_attach (GTK_GRID (grid), button, 2, 0, 1, 1); /*創建標簽*/ label = gtk_label_new("label"); /*布局容器里*/ gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 3, 1); /*窗口接收鼠標事件*/ // GDK_BUTTON_PRESS_MASK:鼠標點擊事件 // GDK_BUTTON_MOTION_MASK:按住鼠標移動事件 gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK); // "button-press-event" 與 deal_mouse_event 連接,鼠標點擊事件 g_signal_connect(window, "button-press-event", G_CALLBACK(deal_mouse_press), NULL); // "motion-notify-event" 與 deal_motion_notify_event 連接,按住鼠標移動事件 g_signal_connect(window, "motion-notify-event", G_CALLBACK(deal_motion_notify_event), NULL); /* 顯示 */ gtk_widget_show_all (window); /* 所有的 GTK 程序必須有一個 gtk_main() 函數。程序運行停在這里 * 等待事件 (如鍵盤事件或鼠標事件) 的發生。*/ gtk_main (); return 0; }