本來想接上篇把關於窗口方面的寫的更詳盡一點,但因為我做軟件的習慣來說還暫時用不不到、我們先跳過,然后先說說窗口中的布局。跟大多數軟件界面一樣,一般包含標題欄、菜單欄、工具欄、狀態欄和工作區等。
首先,我必須要有一個初步的規划,因為是自己設計一些軟件,我只需要問我自己幾個問題(why/how),而不需要跟設計部進行溝通。
1.Q:為什么要設計這個demo?
A:初步認識GTK+的構件並應用到實際開發中,實現掌握GTK+的能力並能分享給大家。
2.Q:如何分享?demo有什么功能?
A:我通過逐步添加代碼的方式,高亮顯示能看到代碼進化的過程,讓本系列讀者達到學習的目的;要全面接觸到所有的GTK+的構建,那么只有把demo做成GTK+構件演示軟件才能滿足了。
3.Q:demo的界面大致是怎么樣的?
A:基本的軟件界面,通過菜單、工具欄等方式逐步演示界面上顯示不到的功能。
4.Q:怎么樣去划分demo的功能?
A:根據Glade 3中的划分,GTK+構建分為Toplevels、Containers、Controls and Display、Composite Widgets等類型。所以在菜單設計中可以按這個分類去設計。
好了,現在應該基本知道未來的demo大概是個什么樣的了吧。
一、添加簡單菜單欄,以后在逐步完善
在添加菜單欄之前、還需要用一個容器來將窗體划分為多個區域,以供放工具欄、狀態欄等.我們從上到下分4欄,最上面是菜單欄,緊接着是工具欄,然后是工作區,最下面是狀態欄。我們先添加一個容器vbox來划分區域,並加入toggle菜單。這個菜單的功能是讓用戶可以操作划分區域的顯示和隱藏。
#include <gtk/gtk.h> /* @Description: 從一個圖片中獲取信息得到pixbuf @param: gchar filename */ GdkPixbuf *create_pixbuf(const gchar * filename) { GdkPixbuf *pixbuf; GError *error = NULL; /* * 函數gdk_pixbuf_new_from_file() 從一個圖片文件中加載圖象數據,從而生成一個新的 pixbuf, * 至於文件中包含圖象的格式,是由系統自動檢測的。如果該函數返回值是NULL 的話,程序就會出現錯誤。 */ pixbuf = gdk_pixbuf_new_from_file(filename, &error); if(!pixbuf) { fprintf(stderr, "%s\n", error->message); g_error_free(error); } return pixbuf; } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; //盒裝容器 GtkWidget *menubar; //菜單欄 GtkWidget *menutoggle, *menu_tog_toggle,*menu_tog_toolbar, *menu_tog_statusbar; //界面開關菜單 //GtkWidget *menu_about, *menu_about_us; //幫助菜單 /*初始化整個GTK+程序,是每一個GTK+程序必不可少的部分*/ gtk_init(&argc, &argv); /*這里生成了一個窗口構件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的標題欄和邊框,同意用窗口管理器來進行管理*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*設置窗口標題*/ gtk_window_set_title(GTK_WINDOW(window), "一步一步學GTK+ DEMO"); /*設置窗口默認大小*/ gtk_window_set_default_size(GTK_WINDOW(window), 500, 400); /* * 設置窗口在顯示器中的位置為居中。 * GTK_WIN_POS_NONE :不固定 * GTK_WIN_POS_CENTER : 居中 * GTK_WIN_POS_MOUSE : 出現在鼠標位置 * GTK_WIN_POS_CENTER_ALWAYS : 窗口改變大小的時候仍然居中 */ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函數gtk_window_set_icon() 是為窗口設置圖標用的,函數create_pixbuf是我們自定義的,目的是從一個圖片中獲取信息得到pixbuf。*/ gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("./images/bear.png"));
/*創建一個盒裝容器並添加到窗口中*/ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /*創建菜單*/ menubar = gtk_menu_bar_new(); //代表整個菜單,是一個menu shell menutoggle = gtk_menu_new(); //這里代表第一列菜單toggle ,也是一個menu shell menu_tog_toggle = gtk_menu_item_new_with_label("widget toggle"); menu_tog_toolbar = gtk_menu_item_new_with_label("show Toolbar"); //toggle 菜單中子項 menu_tog_statusbar = gtk_menu_item_new_with_label("show Statusbar"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_tog_toggle), menutoggle); //widget toggle菜單加入 menutoggle menu shell gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_toolbar); gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_statusbar); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menu_tog_toggle); /*把菜單加入盒子容器*/ gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3); /***********************************以下是信號處理部分************************************/ /*關閉窗口時退出主循環*/ g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL); /***********************************以下是顯示控件部分************************************/ /*開始顯示窗口*/ //gtk_widget_show(window); gtk_widget_show_all(window); gtk_main(); return 0; }

二、添加狀態欄,並點擊任意菜單的時候在狀態來顯示內容
#include <gtk/gtk.h> /* @Description: 從一個圖片中獲取信息得到pixbuf @param: gchar filename */ GdkPixbuf *create_pixbuf(const gchar * filename) { GdkPixbuf *pixbuf; GError *error = NULL; /* * 函數gdk_pixbuf_new_from_file() 從一個圖片文件中加載圖象數據,從而生成一個新的 pixbuf, * 至於文件中包含圖象的格式,是由系統自動檢測的。如果該函數返回值是NULL 的話,程序就會出現錯誤。 */ pixbuf = gdk_pixbuf_new_from_file(filename, &error); if(!pixbuf) { fprintf(stderr, "%s\n", error->message); g_error_free(error); } return pixbuf; } /*點擊菜單時,狀態欄顯示*/ void menu_pressed(GtkWidget *widget, gpointer window) { gchar *str; str = g_strdup_printf("you clicked one menu item"); gtk_statusbar_push(GTK_STATUSBAR(window),gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str); g_free(str); } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; //盒裝容器 GtkWidget *menubar; //菜單欄 GtkWidget *menutoggle, *menu_tog_toggle,*menu_tog_toolbar, *menu_tog_statusbar; //界面開關菜單 //GtkWidget *menu_about, *menu_about_us; //幫助菜單 GtkWidget *statusbar; //狀態欄 /*初始化整個GTK+程序,是每一個GTK+程序必不可少的部分*/ gtk_init(&argc, &argv); /*這里生成了一個窗口構件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的標題欄和邊框,同意用窗口管理器來進行管理*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*設置窗口標題*/ gtk_window_set_title(GTK_WINDOW(window), "一步一步學GTK+ DEMO"); /*設置窗口默認大小*/ gtk_window_set_default_size(GTK_WINDOW(window), 500, 400); /* * 設置窗口在顯示器中的位置為居中。 * GTK_WIN_POS_NONE :不固定 * GTK_WIN_POS_CENTER : 居中 * GTK_WIN_POS_MOUSE : 出現在鼠標位置 * GTK_WIN_POS_CENTER_ALWAYS : 窗口改變大小的時候仍然居中 */ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函數gtk_window_set_icon() 是為窗口設置圖標用的,函數create_pixbuf是我們自定義的,目的是從一個圖片中獲取信息得到pixbuf。*/ gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("./images/bear.png")); /*創建一個盒裝容器並添加到窗口中*/ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /*創建菜單*/ menubar = gtk_menu_bar_new(); //代表整個菜單,是一個menu shell menutoggle = gtk_menu_new(); //這里代表第一列菜單toggle ,也是一個menu shell menu_tog_toggle = gtk_menu_item_new_with_label("widget toggle"); menu_tog_toolbar = gtk_menu_item_new_with_label("show Toolbar"); //toggle 菜單中子項 menu_tog_statusbar = gtk_menu_item_new_with_label("show Statusbar"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_tog_toggle), menutoggle); //widget toggle菜單加入 menutoggle menu shell gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_toolbar); gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_statusbar); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menu_tog_toggle); /*把菜單加入盒子容器*/ gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 4); statusbar = gtk_statusbar_new(); gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, 1); /***********************************以下是信號處理部分************************************/ /*關閉窗口時退出主循環*/ g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(menu_tog_toolbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar)); g_signal_connect(G_OBJECT(menu_tog_statusbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar)); /***********************************以下是顯示控件部分************************************/ /*開始顯示窗口*/ //gtk_widget_show(window); gtk_widget_show_all(window); gtk_main(); return 0; }
狀態欄的相關函數:
guint gtk_statusbar_push (GtkStatusbar *statusbar, guint context_id, const gchar *text); void gtk_statusbar_pop (GtkStatusbar *statusbar, guint context_id); void gtk_statusbar_remove (GtkStatusbar *statusbar, guint context_id, guint message_id); void gtk_statusbar_remove_all (GtkStatusbar *statusbar, guint context_id);
三、添加工具欄,並給“退出”按鈕加入信號
#include <gtk/gtk.h> /* @Description: 從一個圖片中獲取信息得到pixbuf @param: gchar filename */ GdkPixbuf *create_pixbuf(const gchar * filename) { GdkPixbuf *pixbuf; GError *error = NULL; /* * 函數gdk_pixbuf_new_from_file() 從一個圖片文件中加載圖象數據,從而生成一個新的 pixbuf, * 至於文件中包含圖象的格式,是由系統自動檢測的。如果該函數返回值是NULL 的話,程序就會出現錯誤。 */ pixbuf = gdk_pixbuf_new_from_file(filename, &error); if(!pixbuf) { fprintf(stderr, "%s\n", error->message); g_error_free(error); } return pixbuf; } /*點擊菜單時,狀態欄顯示*/ void menu_pressed(GtkWidget *widget, gpointer window) { gchar *str; str = g_strdup_printf("you click one menu item"); gtk_statusbar_push(GTK_STATUSBAR(window),gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str); g_free(str); } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; //盒裝容器 GtkWidget *menubar; //菜單欄 GtkWidget *menutoggle, *menu_tog_toggle,*menu_tog_toolbar, *menu_tog_statusbar; //界面開關菜單 //GtkWidget *menu_about, *menu_about_us; //幫助菜單 GtkWidget *toolbar; //工具欄 GtkToolItem *tool_exit, *tool_sep,*tool_about; GtkWidget *statusbar; //狀態欄 /*初始化整個GTK+程序,是每一個GTK+程序必不可少的部分*/ gtk_init(&argc, &argv); /*這里生成了一個窗口構件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的標題欄和邊框,同意用窗口管理器來進行管理*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*設置窗口標題*/ gtk_window_set_title(GTK_WINDOW(window), "一步一步學GTK+ DEMO"); /*設置窗口默認大小*/ gtk_window_set_default_size(GTK_WINDOW(window), 500, 400); /* * 設置窗口在顯示器中的位置為居中。 * GTK_WIN_POS_NONE :不固定 * GTK_WIN_POS_CENTER : 居中 * GTK_WIN_POS_MOUSE : 出現在鼠標位置 * GTK_WIN_POS_CENTER_ALWAYS : 窗口改變大小的時候仍然居中 */ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函數gtk_window_set_icon() 是為窗口設置圖標用的,函數create_pixbuf是我們自定義的,目的是從一個圖片中獲取信息得到pixbuf。*/ gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("./images/bear.png")); /*創建一個盒裝容器並添加到窗口中*/ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /*創建菜單*/ menubar = gtk_menu_bar_new(); //代表整個菜單,是一個menu shell menutoggle = gtk_menu_new(); //這里代表第一列菜單toggle ,也是一個menu shell menu_tog_toggle = gtk_menu_item_new_with_label("View"); menu_tog_toolbar = gtk_menu_item_new_with_label("show Toolbar"); //toggle 菜單中子項 menu_tog_statusbar = gtk_menu_item_new_with_label("show Statusbar"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_tog_toggle), menutoggle); //widget toggle菜單加入 menutoggle menu shell gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_toolbar); gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_statusbar); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menu_tog_toggle); //創建工具欄 toolbar = gtk_toolbar_new(); gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); //設置工具欄樣式為圖標 gtk_container_set_border_width(GTK_CONTAINER(toolbar), 0); //工具欄邊框大小 tool_exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT); //工具欄中的 “退出” 按鈕 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_exit, -1); tool_sep = gtk_separator_tool_item_new(); //工具欄中按鈕之間的分割線 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_sep, -1); tool_about = gtk_tool_button_new_from_stock(GTK_STOCK_HELP); //工具欄中的“關於” 按鈕 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_about, -1); statusbar = gtk_statusbar_new(); /*把菜單加入盒子容器*/ gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 1); /*把工具欄加入盒子容器*/ gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); /*把狀態欄加入盒子最下面*/ gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, 1); /***********************************以下是信號處理部分************************************/ /*關閉窗口時退出主循環*/ g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(tool_exit), "clicked",G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(menu_tog_toolbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar)); g_signal_connect(G_OBJECT(menu_tog_statusbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar)); /***********************************以下是顯示控件部分************************************/ /*開始顯示窗口*/ //gtk_widget_show(window); gtk_widget_show_all(window); gtk_main(); return 0; }

四、選擇(Check)菜單選項(menu item)
移除剛才菜單點時候狀態欄顯示的功能,新增功能——控制工具欄和狀態欄的顯示/隱藏。
#include <gtk/gtk.h> /* @Description: 從一個圖片中獲取信息得到pixbuf @param: gchar filename */ GdkPixbuf *create_pixbuf(const gchar * filename) { GdkPixbuf *pixbuf; GError *error = NULL; /* * 函數gdk_pixbuf_new_from_file() 從一個圖片文件中加載圖象數據,從而生成一個新的 pixbuf, * 至於文件中包含圖象的格式,是由系統自動檢測的。如果該函數返回值是NULL 的話,程序就會出現錯誤。 */ pixbuf = gdk_pixbuf_new_from_file(filename, &error); if(!pixbuf) { fprintf(stderr, "%s\n", error->message); g_error_free(error); } return pixbuf; } /*點擊菜單時,狀態欄顯示*/ /* void menu_pressed(GtkWidget *widget, gpointer window) { gchar *str; str = g_strdup_printf("you click one menu item"); gtk_statusbar_push(GTK_STATUSBAR(window),gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str); g_free(str); } */ //根據菜單欄的選擇(check)控制一些構件的顯示和隱藏 void toggle_display(GtkWidget *widget, gpointer oneofwidget) { if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { gtk_widget_show(oneofwidget); } else { gtk_widget_hide(oneofwidget); } } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *vbox; //盒裝容器 GtkWidget *menubar; //菜單欄 GtkWidget *menutoggle, *menu_tog_toggle,*menu_tog_toolbar, *menu_tog_statusbar; //界面開關菜單 //GtkWidget *menu_about, *menu_about_us; //幫助菜單 GtkWidget *toolbar; //工具欄 GtkToolItem *tool_exit, *tool_sep,*tool_about; GtkWidget *statusbar; //狀態欄 /*初始化整個GTK+程序,是每一個GTK+程序必不可少的部分*/ gtk_init(&argc, &argv); /*這里生成了一個窗口構件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的標題欄和邊框,同意用窗口管理器來進行管理*/ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*設置窗口標題*/ gtk_window_set_title(GTK_WINDOW(window), "一步一步學GTK+ DEMO"); /*設置窗口默認大小*/ gtk_window_set_default_size(GTK_WINDOW(window), 500, 400); /* * 設置窗口在顯示器中的位置為居中。 * GTK_WIN_POS_NONE :不固定 * GTK_WIN_POS_CENTER : 居中 * GTK_WIN_POS_MOUSE : 出現在鼠標位置 * GTK_WIN_POS_CENTER_ALWAYS : 窗口改變大小的時候仍然居中 */ gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函數gtk_window_set_icon() 是為窗口設置圖標用的,函數create_pixbuf是我們自定義的,目的是從一個圖片中獲取信息得到pixbuf。*/ gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("./images/bear.png")); /*創建一個盒裝容器並添加到窗口中*/ vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /*創建菜單*/ menubar = gtk_menu_bar_new(); //代表整個菜單,是一個menu shell menutoggle = gtk_menu_new(); //這里代表第一列菜單toggle ,也是一個menu shell menu_tog_toggle = gtk_menu_item_new_with_label("View"); //menu_tog_toolbar = gtk_menu_item_new_with_label("show Toolbar"); //toggle 菜單中子項 //menu_tog_statusbar = gtk_menu_item_new_with_label("show Statusbar"); menu_tog_toolbar = gtk_check_menu_item_new_with_label("show Toolbar"); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_tog_toolbar),TRUE); menu_tog_statusbar = gtk_check_menu_item_new_with_label("show Statusbar"); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_tog_statusbar),TRUE); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_tog_toggle), menutoggle); //widget toggle菜單加入 menutoggle menu shell gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_toolbar); gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_statusbar); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menu_tog_toggle); //創建工具欄 toolbar = gtk_toolbar_new(); gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); //設置工具欄樣式為圖標 gtk_container_set_border_width(GTK_CONTAINER(toolbar), 0); //工具欄邊框大小 tool_exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT); //工具欄中的 “退出” 按鈕 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_exit, -1); tool_sep = gtk_separator_tool_item_new(); //工具欄中按鈕之間的分割線 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_sep, -1); tool_about = gtk_tool_button_new_from_stock(GTK_STOCK_HELP); //工具欄中的“關於” 按鈕 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_about, -1); statusbar = gtk_statusbar_new(); /*把菜單加入盒子容器*/ gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 1); /*把工具欄加入盒子容器*/ gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); /*把狀態欄加入盒子最下面*/ gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, 1); /***********************************以下是信號處理部分************************************/ /*關閉窗口時退出主循環*/ g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(tool_exit), "clicked",G_CALLBACK(gtk_main_quit), NULL); //g_signal_connect(G_OBJECT(menu_tog_toolbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar)); //g_signal_connect(G_OBJECT(menu_tog_statusbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar)); g_signal_connect(G_OBJECT(menu_tog_toolbar), "activate",G_CALLBACK(toggle_display), toolbar); g_signal_connect(G_OBJECT(menu_tog_statusbar), "activate",G_CALLBACK(toggle_display), statusbar); /***********************************以下是顯示控件部分************************************/ /*開始顯示窗口*/ //gtk_widget_show(window); gtk_widget_show_all(window); gtk_main(); return 0; }

