註:這一節是我新譯的因為簡體版的沒有翻譯這一篇,如果有翻的不妥處尚請指教。
現在我們已經介紹了難的辦法,這裡介紹怎樣用 gtk_item_factory 呼叫來做。ItemFactory 從ItemFactory entries的陣列中創建選單,他的意思就是你可以用最簡單的格式來定義你的選單然後用最少的函式呼叫創建選單/功能欄元件。
ItemFactory entries
ItemFactory 的核心就是 ItemFactoryEntry,這個結構定義了一個選單項並且當這些項目的陣列定義之後整個選單就形成了,ItemFactory entry struct 定義看起來像這樣:
struct _GtkItemFactoryEntry{gchar *path;gchar *accelerator; GtkItemFactoryCallback callback;guint callback_action; gchar *item_type; }; |
每個欄位定義了部分的選單項。
*path 是一個字串定義了選單項的名稱及路徑,舉個例來說,”/File/Open” 是選單項的名字,這個名字歸入在 ItemFactory entry 的路徑”/File”裡,但是注意”/File/Open” 會出現在 File 選單中的”Open”功能欄,另外要注意”/”被用來定義選單的路徑,字母前面加底線表示他是快捷鍵當選單開啟時就可以用。
*accelerator 是一個字串用來說明該選單項目的快捷建的組合鍵,這個字串是由單一字元或是單一字元的輔助按鍵的組合所做成,大小寫不區分。
可用的輔助按鍵有:
"<ALT> - alt"<CTL>" or "<CTRL>" or "<CONTROL>" - control"<MOD1>" to "<MOD5>" - modn"<SHFT>" or "<SHIFT>" - shift |
範例:
"<ConTroL>a""<SHFT><ALT><CONTROL>X" |
callback 是當選單項目引發”activate”信號時被呼叫的函式,回呼函式的格式在後面回呼函式的描述中討論。
callback_action 的值會傳給回呼函式,他也會影響函式的原型(prototype)在回呼函式的描述中說明。
item_type 是一個字串定義了元件被封裝入選單項目容器中的型別,它像這樣:
NULL or "" or "<Item>" - create a simple item"<Title>" - create a title item"<CheckItem>" - create a check item"<ToggleItem>" - create a toggle item"<RadioItem>" - create a (root) radio item "Path" - create a sister radio item "<Tearoff>" - create a tearoff "<Separator>" - create a separator "<Branch>" - create an item to hold submenus (optional) "<LastBranch>" - create a right justified branch "<StockItem>" - create a simple item with a stock image. see gtkstock.h for builtin stock items |
注意 <LastBranch> 只有在功能欄的子選單中有效。
回呼函式的描述
ItemFactory entry 的回呼函式有兩種格式,假如 callback_action 是0,格式如下:
void callback( void ) |
另外的格式如下:
void callback( gpointer callback_data, guint callback_action,GtkWidget *widget ) |
callback_data 任意資料的指標,它在呼叫gtk_item_factory_create_items()時被設定。
callback_action 跟在ItemFactory entry裡的callback_action 值一樣。
*widget 是選單項目元件的指標 (在選單元件中有討論)。
ItemFactory entry 範例
創建簡單的選單項目:
GtkItemFactoryEntry entry = {"/_File/_Open...", "<CTRL>O", print_hello, 0, "<Item>"}; |
這一行定義了一個簡單的選單項目 “/File/Open” (會顯示 “Open”),在 “/File” 選單項目下,當按下呼叫函式print_hello()時它有快捷鍵 control+’O’ , print_hello() 的格式是 void print_hello(void) 因為它的 callback_action 欄位是0,當”Open”的 ‘O’ 被加底線顯示時以及在螢幕上按下’O’時選單項目是可見的時候會啟用它們,注意 “File/_Open” 也可以用來替換 “/_File/_Open”。
用更複雜的回呼函式來創建項目:
GtkItemFactoryEntry entry = {"/_View/Display _FPS", NULL, print_state, 7,"<CheckItem>"}; |
這一行定義了一個新的選單項目會顯示 “Display FPS” 在”View”的選單項目下,當按下 print_state() 函式時會被呼叫,因為 callback_action 不是0所以 print_state() 格式是這樣:
void print_state( gpointer callback_data, guint callback_action,GtkWidget *widget ) |
callback_action 的值是 7。
創建圓鈕集:
GtkItemFactoryEntry entry1 = {"/_View/_Low Resolution", NULL, change_resolution, 1, "<RadioButton>"};GtkItemFactoryEntry entry2 = {"/_View/_High Resolution", NULL, change_resolution,2, "/View/Low Resolution"}; |
entry1 定義了一個單一的圓鈕當處變呼叫函式change_resolution() 的參數時 callback_action 等於1。 change_resolution() 的格式:
void change_resolution(gpointer callback_data, guint callback_action,GtkWidget *widget) |
entry2 定義了一個圓鈕,這個圓鈕屬於entry1所屬的圓鈕這組,它呼叫相同的函式但是參數 callback_action 等於 2,注意entry2的 item_type 是沒有 (‘_’)的快速鍵的entry1的路徑,假如另一個圓鈕需要在相同的組合中那麼他可以用相同的方式來定義就像 entry2 有 item_type 而他的值是 “/View/Low Resolution”。
ItemFactoryEntry 陣列
ItemFactoryEntry 在它自己上不是很有用,entries的陣列是需要定義的,下面是你如何宣告這陣列的範例。
static GtkItemFactoryEntry entries[] = { { "/_File", NULL, NULL, 0, "<Branch>" },{ "/File/tear1", NULL, NULL, 0, "<Tearoff>" },{ "/File/_New", "<CTRL>N", new_file, 1, "<Item>" },{ "/File/_Open...", "<CTRL>O", open_file, 1, "<Item>" }, { "/File/sep1", NULL, NULL, 0, "<Separator>" }, { "/File/_Quit", "<CTRL>Q", quit_program, 0, "<StockItem>", GTK_STOCK_QUIT } }; |
創建一個 ItemFactory
GtkItemFactoryEntry 項目的陣列定義了選單,一旦陣列被定義這個 item factory 就會被創建,這個函式可以這樣用:
GtkItemFactory* gtk_item_factory_new( GtkType container_type, const gchar *path,GtkAccelGroup *accel_group ); |
container_type 可以是下列其中一個值:
GTK_TYPE_MENUGTK_TYPE_MENU_BARGTK_TYPE_OPTION_MENU |
container_type 定義了你要的選單型態,所以當你擷取它的時候,它不是選單 (例如彈出式)就是選項選單 (像是複合方塊但是有下拉選單)。
path 定義選單的根的路徑,基本上它是選單根的名稱,必需用”<>”括起來,這對快捷鍵的名稱來說很重要而且應該是唯一的,每個選單和每個程式之間也應該是唯一的, 舉個例來說一個程式名稱叫 ‘foo’,它的主選單就應該叫做 “<FooMain>”,而彈出選單 “<FooImagePopUp>”或者類似,很重要的一個地方就是這些名稱都是唯一的。
accel_group 是一個gtk_accel_group的指標,item factory 會在產生選單時設定快捷鍵表格,新的快捷鍵組合由 gtk_accel_group_new()產生。
但這只是第一步,要轉換 GtkItemFactoryEntry 資訊的陣列到元件會使用下列的函式:
void gtk_item_factory_create_items( GtkItemFactory *ifactory, guint n_entries,GtkItemFactoryEntry *entries,gpointer callback_data ); |
*ifactory 是上面產生的 item factory 指標。
n_entries 是GtkItemFactoryEntry 陣列的項目數目。
*entries 是GtkItemFactoryEntry 陣列的指標。
callback_data 是所有callback_action != 0時傳給回呼函式的資料。
快捷鍵組現在已形成,所以你可能要連結它到視窗這個選單在裡面:
void gtk_window_add_accel_group( GtkWindow *window, GtkAccelGroup *accel_group); |
使用選單及選單項目
最後要做的就是使用選單,下列的函式從ItemFactory擷取相關的元件:
GtkWidget* gtk_item_factory_get_widget( GtkItemFactory *ifactory, const gchar *path ); |
舉例來說假如有一個 ItemFactory 有兩個項目 “/File” 及 “/File/New”,使用 “/File” 路徑會從ItemFactory 擷取一個 menu 元件,使用 “/File/New” 路徑會擷取一個選單項目元件, 這使得它可以設定選單項目的初始狀態,舉個例來說要設初始的圓鈕項目到 “/Shape/Oval” 路徑的其中一個可以使用下面的程式碼:
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory, "/Shape/Oval")),TRUE); |
最後要擷取選單的根使用 gtk_item_factory_get_item() 有 “<main>” 的路徑(或是使用gtk_item_factory_new() 而不管其路徑), 在 ItemFactory擁有型別 GTK_TYPE_MENU_BAR 產生的情況下會傳回功能欄元件,使用型別 GTK_TYPE_MENU 會傳回選單元件, 使用型別 GTK_TYPE_OPTION_MENU 會傳回選項選單元件。
記得 “/_File” 路徑定義的項目在這裡真的是 “/File”。
現在你有 功能欄 或 選單 這些元件同樣也可以在 選單元件 這一節所討論的方式來處理。
2 則留言