有兩種創建選單的方法:一個容易的,一種難的。它們各有各的用處,不過一般你可以使用套件(Itemfactory)(容易的方法)。「難」的方法是直接使用呼叫來創建所有的選單。容易的方法是使用 gtk_item_factory 呼叫。這要簡單得多,但每種方法各有優點和缺點。
套件要容易使用得多,加新的選單也方便些,雖然用手動方法寫一些外包(wrapper)函式來創建選單能對可用性大有幫助。使用套件,不能在選單上增加圖片或 ‘/’ 字符。
手動創建選單
按照現實教學中的慣例,我們將先介紹難的方法。
創建選單欄和子選單時要用到三種元件:
- 一個選單項(menu item),就是用戶要選擇的東西,比如,”Save”
- 一個選單(menu),作為選單項的容器,以及
- 一個選單欄(menubar),是各個單獨選單的容器。
選單項元件有兩個不同的用處,這情況有一點複雜。既有封裝到選單裡的元件,也有封裝到選單欄中,當被選中時啟用選單的元件。
讓我們看一下用來創建選單和選單欄的函式。第一個函式用來創建一個新的選單欄。
GtkWidget *gtk_menu_bar_new( void ); |
這個不太需要加以說明的函式創建一個新的選單欄。你用 gtk_container_add() 封裝它到一個視窗,或盒組裝(box_pack)函式來將它封裝到一個盒子中 - 就像按鈕一樣。
GtkWidget *gtk_menu_new( void ); |
這個函式傳回指向一個新選單的指標。它從不會真正顯示(用 gtk_widget_show()),它只是一個選單項的容器。我希望你看了後面的範例後會弄清楚一些。
接下來的三個呼叫用來創建被封裝到選單(和選單欄)中的選單項。
GtkWidget *gtk_menu_item_new( void ); GtkWidget *gtk_menu_item_new_with_label( const char *label ); GtkWidget *gtk_menu_item_new_with_mnemnonic( const char *label ); |
這些呼叫用來創建將顯示的選單項。記住要區別用 gtk_menu_new() 創建的「選單」和用 gtk_menu_item_new() 函式創建的「選單項」。有了相關聯動作的選單項將是一個真實的按鈕,而選單將是一個包含選單項的容器。
gtk_menu_item_new_with_label() 和 gtk_menu_item_new() 函式正如你讀了按鈕部分後料想的一樣。其一創建一個已經有一個標籤封封裝進來了的新的選單項,另一個僅僅創建一個空白的選單項。
在創建一個選單項後你要將它放到一個選單裡。用函式 gtk_menu_append 就行了。為了擷取何時這個項被用戶選中,我們要用平常的方法連接到activate信號。所以,如果我們要創建一個標準的File選單,包括Open,Save和Quit選項,程式碼將像這樣:
file_menu = gtk_menu_new (); /* 不必顯示選單 */ /* 創建選單項 */ open_item = gtk_menu_item_new_with_label ("Open"); save_item = gtk_menu_item_new_with_label ("Save"); quit_item = gtk_menu_item_new_with_label ("Quit"); /* 將它們加到選單中 */ gtk_menu_append (GTK_MENU (file_menu), open_item); gtk_menu_append (GTK_MENU (file_menu), save_item); gtk_menu_append (GTK_MENU (file_menu), quit_item); /* 將回呼函式系結到activate信號 */ g_signal_connect_swapped (G_OBJECT (open_item), "activate", G_CALLBACK (menuitem_response), (gpointer) "file.open"); g_signal_connect_swapped (G_OBJECT (save_item), "activate", G_CALLBACK (menuitem_response), (gpointer) "file.save"); /* 我們可以系結Quit選單項到我們的退出函式 */ g_signal_connect_swapped (G_OBJECT (quit_item), "activate", G_CALLBACK (destroy), (gpointer) "file.quit"); /* 一定要顯示選單項 */ gtk_widget_show (open_item); gtk_widget_show (save_item); gtk_widget_show (quit_item); |
這時我們有了我們的選單。現在我們要創建一個選單欄,並為File項目(entry)創建一個選單項,我們的選單就加在這個上。程式碼看起來像這樣:
menu_bar = gtk_menu_bar_new (); gtk_container_add (GTK_CONTAINER (window), menu_bar); gtk_widget_show (menu_bar); file_item = gtk_menu_item_new_with_label ("File"); gtk_widget_show (file_item); |
現在我們要把選單和file_item關聯起來。用這個函式可以做到:
void gtk_menu_item_set_submenu( GtkMenuItem *menu_item, GtkWidget *submenu ); |
那麼,我們的範例接下來就是
gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu); |
所有剩下要做的就是將選單加到選單欄,用這個函式完成:
void gtk_menu_bar_append( GtkMenuBar *menu_bar, GtkWidget *menu_item ); |
在我們的情況下就像這樣了:
gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item); |
如果我們想讓選單在選單欄上右對齊,例如幫助選單就經常是這樣,我們可以在系結它到選單欄之前使用下面的函式(本例中又是對file_item使用)。
void gtk_menu_item_right_justify( GtkMenuItem *menu_item ); |
這裡是一個對創建一個附帶了選單的選單欄所需步驟的概要:
- 用 gtk_menu_new() 創建一個新的選單
- 多次呼叫 gtk_menu_item_new() 創建每個你想在你的選單上出現的選單項。並使用 gtk_menu_append() 將每個新的選單項放到選單上。
- 用 gtk_menu_item_new() 創建一個選單項。這將是選單的根(root),這裡所顯示的文字就是選單欄上出現的字。
- 用 gtk_menu_item_set_submenu() 將選單系結到根選單項(就是上一步創建的那個)。
- 用 gtk_menu_bar_new 創建一個新的選單欄。在一個選單欄上創建一系列選單時這步只要做一次就行了。
- 用 gtk_menu_bar_append() 將根選單項放到選單欄上。
創建一個彈出選單幾乎也一樣。不同的是選單不會被選單欄「自動」彈出,而是在button-press事件(例如)裡呼叫函式 gtk_menu_popup() 時明確地彈出。有這些步驟:
- 創建一個事件處理函式。它要有如下原型:
static gint handler (GtkWidget *widget, GdkEvent *event);
並且它會根據event得到選單彈出的地方。
- 在事件處理函式裡,如果這是一個滑鼠按鈕按下事件,把event當作滑鼠按鍵事件(本來就是)並像範例程式碼那樣利用它傳遞訊息給gtk_menu_popup()。
- 系結那個事件處理函式到一個元件用
g_signal_connect_swapped (G_OBJECT (widget), "event", G_CALLBACK (handler), G_OBJECT (menu));
其中widget是你要系結到的元件,handler是處理函式,而menu是一個用 gtk_menu_new() 創建的選單。它可以是一個也被選單欄彈出的選單,範例程式碼裡就做了示範。
3 則留言