工具欄(Toolbars)常用來將一些元件分組,這樣能夠簡化定製它們的外觀和佈局。典型情況下工具欄由帶圖示和標籤以及工具提示的按鈕組成,不過,其它元件也可以放在工具欄裡面。最後,各工具欄組件可以水平或垂直排列,還可以顯示圖示或標籤,或者兩者都顯示。
用下面的函式創建一個工具欄(可能有些人已經猜到了):
GtkWidget *gtk_toolbar_new( void ); |
創建工具欄以後,可以向其中追加、前插和插入工具欄項(這裡意指簡單文字字串)或元素(這裡意指任何元件類型)。要想描述一個工具欄上的物件,需要一個標籤文字、一個工具提示文字、一個私有工具提示文字、一個圖示和一個回呼函式。例如,要前插或追加一個按鈕,應該使用下面的函式:
GtkWidget *gtk_toolbar_append_item( GtkToolbar *toolbar, const char *text, const char *tooltip_text, const char *tooltip_private_text, GtkWidget *icon, GtkSignalFunc callback, gpointer user_data ); GtkWidget *gtk_toolbar_prepend_item( GtkToolbar *toolbar, const char *text, const char *tooltip_text, const char *tooltip_private_text, GtkWidget *icon, GtkSignalFunc callback, gpointer user_data ); |
如果要使用 gtk_toolbar_insert_item(),除上面函式中要指定的參數以外,還要指定插入物件的位置,形式如下:
GtkWidget *gtk_toolbar_insert_item( GtkToolbar *toolbar, const char *text, const char *tooltip_text, const char *tooltip_private_text, GtkWidget *icon, GtkSignalFunc callback, gpointer user_data, gint position ); |
要簡單地在工具欄項之間添加空白區域,可以使用下面的函式:
void gtk_toolbar_append_space( GtkToolbar *toolbar ); void gtk_toolbar_prepend_space( GtkToolbar *toolbar ); void gtk_toolbar_insert_space( GtkToolbar *toolbar, gint position ); |
如果需要,工具欄的放置方向和它的式樣可以在不工作時用下面的函式設置:
void gtk_toolbar_set_orientation( GtkToolbar *toolbar, GtkOrientation orientation ); void gtk_toolbar_set_style( GtkToolbar *toolbar, GtkToolbarStyle style ); void gtk_toolbar_set_tooltips( GtkToolbar *toolbar, gint enable ); |
上面的orientation參數取GTK_ORIENTATION_HORIZONTAL或GTK_ORIENTATION_VERTICAL。style參數用於設置工具欄項的外觀,可以取GTK_TOOLBAR_ICONS,GTK_TOOLBAR_TEXT或GTK_TOOLBAR_BOTH。
要想瞭解工具欄還能做什麼,看一看下面的程式(在程式碼之間我們插入了一些解釋):
#include <gtk/gtk.h> /* 這個函式連接到Close按鈕或者從視窗管理器關閉視窗的事件上 */ gint delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) { gtk_main_quit (); return FALSE; } |
上面的程式碼和其它的 GTK 應用程式差別不大,有一點不同的是:我們包含了一個漂亮的 XPM 圖片,用作所有按鈕的圖示。
GtkWidget* close_button; /* 這個按鈕將引發一個信號以 * 關閉應用程式 */ GtkWidget* tooltips_button; /* 啟用/停用工具提示 */ GtkWidget* text_button, * icon_button, * both_button; /* 切換工具欄風格的單選按鈕 */ GtkWidget* entry; /* 一個文字輸入元件,用於說明任何元件都可以封裝到 * 工具欄裡 */ |
事實上,不是上面所有的元件都是必須的,我把它們放在一起,是為了讓事情更清晰。
/* 很簡單...當按鈕進行狀態切換時,我們檢查哪一個按鈕是活動的,依此設置工具欄的式樣 * 注意,工具欄是作為用戶資料傳遞到回呼函式的! */ void radio_event (GtkWidget *widget, gpointer data) { if (GTK_TOGGLE_BUTTON (text_button)->active) gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT); else if (GTK_TOGGLE_BUTTON (icon_button)->active) gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS); else if (GTK_TOGGLE_BUTTON (both_button)->active) gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH); } /* 更簡單,檢查給定開關按鈕的狀態,依此啟用或停用工具提示 */ void toggle_event (GtkWidget *widget, gpointer data) { gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), GTK_TOGGLE_BUTTON (widget)->active ); } |
上面只是當工具欄上的一個按鈕被按下時要呼叫的兩個回呼函式。你應該已經熟悉了這些東西,如果你已經使用過開關按鈕(以及單選按鈕)。
int main (int argc, char *argv[]) { /* 下面是主視窗(一個對話框)和一個把手盒(handlebox) */ GtkWidget* dialog; GtkWidget* handlebox; /* 好了,我們需要一個工具欄,一個帶遮罩(mask)的圖示(所有的按鈕共用一個遮罩)以及 * 一個放圖示的圖示元件(但我們會為每個按鈕創建一個分割元件) */ GtkWidget * toolbar; GtkWidget * iconw; /* 這個在所有的 GTK 程式中都被呼叫。 */ gtk_init (&argc, &argv); /* 用給定的標題和尺寸創建一個新視窗 */ dialog = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (dialog), "GTKToolbar Tutorial"); gtk_widget_set_size_request (GTK_WIDGET (dialog), 600, 300); GTK_WINDOW (dialog)->allow_shrink = TRUE; /* 在關閉視窗時退出 */ g_signal_connect (G_OBJECT (dialog), "delete_event", G_CALLBACK (delete_event), NULL); /* 需要實現的視窗,因為我們要在它的內容中為工具欄設置圖片 */ gtk_widget_realize (dialog); /* 我們將工具欄放在一個把手元件(handle box)上, * 這樣它可以從主視窗上移開 */ handlebox = gtk_handle_box_new (); gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), handlebox, FALSE, FALSE, 5); |
上面的程式碼和任何其它Gtk應用程示都差不多。它們進行 GTK 初始化,創建主視窗等。唯一需要解釋的是:一個把手盒(a handle box)。把手盒只是一個可以在其中封裝元件的盒子。它和普通盒子的區別在於它能從一個父視窗移開(事實上,把手盒保留在父視窗上,但是它縮小為一個非常小的矩形,同時它的所有內容重新放在一個新的可自由移動的浮動視窗上)。擁有一個可浮動工具欄給人感覺非常好,所以這兩種元件經常同時使用。
/* 工具欄設置為水平的,同時帶有圖示和文字 * 在每個項之間有5像素的間距, * 並且,我們也將它放在把手盒上 */ toolbar = gtk_toolbar_new (); gtk_toolbar_set_orientation (GTK_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL); gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH); gtk_container_set_border_width (GTK_CONTAINER (toolbar), 5); gtk_toolbar_set_space_size (GTK_TOOLBAR (toolbar), 5); gtk_container_add (GTK_CONTAINER (handlebox), toolbar); |
上面的程式碼初始化工具欄元件。
/* 工具欄上第一項是<close>按鈕 */ iconw = gtk_image_new_from_file ("gtk.xpm"); /* 圖示元件 */ close_button = gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), /* 工具欄 */ "Close", /* 按鈕標籤 */ "Closes this app", /* 按鈕的工具提示 */ "Private", /* 工具提示的私有信息 */ iconw, /* 圖示元件 */ GTK_SIGNAL_FUNC (delete_event), /* 一個信號 */ NULL); gtk_toolbar_append_space (GTK_TOOLBAR (toolbar)); /* 工具欄項後的空白 */ |
在上面的程式碼中,可以看到最簡單的情況:在工具欄上增加一個按鈕。在追加一個新的工具欄項前,必須構造一個圖片(image)元件用作該項的圖示,這個步驟我們要對每一個工具欄項重複一次。在工具欄項之間還要增加間隔空間,這樣後面的工具欄項就不會一個接一個緊挨著。可以看到, gtk_toolbar_append_item()返回一個指向新創建的按鈕元件的指標,所以我們可以用正常的方式使用它。
/* 現在,我們創建單選按鈕組... */ iconw = gtk_image_new_from_file ("gtk.xpm"); icon_button = gtk_toolbar_append_element ( GTK_TOOLBAR (toolbar), GTK_TOOLBAR_CHILD_RADIOBUTTON, /* 元素類型 */ NULL, /* 指向元件的指標 */ "Icon", /* 標籤 */ "Only icons in toolbar", /* 工具提示 */ "Private", /* 工具提示的私有字串 */ iconw, /* 圖示 */ GTK_SIGNAL_FUNC (radio_event), /* 信號 */ toolbar); /* 信號傳遞的資料 */ gtk_toolbar_append_space (GTK_TOOLBAR (toolbar)); |
這裡我們開始創建一個單選按鈕組。用 gtk_toolbar_append_element 就行了。事實上,使用這個函式,我們能夠添加簡單的工具欄項或空白間隔(類型為GTK_TOOLBAR_CHILD_SPACE或GTK_TOOLBAR_CHILD_BUTTON)。在上面的範例中,我們先創建了一個單選按鈕組。要為這個組創建其它單選按鈕,需要一個指向前一個按鈕的指標,這樣按鈕的清單可以很容易組織起來(看在本文件前面部分的單選按鈕節)。
/* 後面的單選按鈕引用前面創建的 */ iconw = gtk_image_new_from_file ("gtk.xpm"); text_button = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_CHILD_RADIOBUTTON, icon_button, "Text", "Only texts in toolbar", "Private", iconw, GTK_SIGNAL_FUNC (radio_event), toolbar); gtk_toolbar_append_space (GTK_TOOLBAR (toolbar)); iconw = gtk_image_new_from_file ("gtk.xpm"); both_button = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_CHILD_RADIOBUTTON, text_button, "Both", "Icons and text in toolbar", "Private", iconw, GTK_SIGNAL_FUNC (radio_event), toolbar); gtk_toolbar_append_space (GTK_TOOLBAR (toolbar)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (both_button), TRUE); |
最後,我們必須手工設置其中一個按鈕的狀態(否則它們全部處於活動狀態,並阻止我們在它們之間做出選擇)。
/* 下面只是一個簡單的開關按鈕 */ iconw = gtk_image_new_from_file ("gtk.xpm"); tooltips_button = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_CHILD_TOGGLEBUTTON, NULL, "Tooltips", "Toolbar with or without tips", "Private", iconw, GTK_SIGNAL_FUNC (toggle_event), toolbar); gtk_toolbar_append_space (GTK_TOOLBAR (toolbar)); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tooltips_button), TRUE); |
開關按鈕的創建方法就很明顯了(如果你已經知道怎麼創建單選按鈕了)。
/* 要將一個元件封裝到工具欄上,只需創建它,然後將它追 * 加到工具欄上,同時設置合適的工具提示 */ entry = gtk_entry_new (); gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), entry, "This is just an entry", "Private"); /* 因為它不是工具欄自己創建的,所以我們還需要顯示它 */ gtk_widget_show (entry); |
可以看到,將任何元件添加到工具欄上都是非常簡單的。唯一要記住的是,這個元件必須手動顯示(與此相反,工具欄自己創建的工具欄項隨工具欄一起顯示)。
/* 好了,現在可以顯示所有的東西了 */ gtk_widget_show (toolbar); gtk_widget_show (handlebox); gtk_widget_show (dialog); /* 進入主循環,等待用戶的操作 */ gtk_main (); return 0; } |
這樣,我們就到了工具欄教學的末尾。當然,還需要一個漂亮的XPM圖示。下面就是:
/* XPM */ static char * gtk_xpm[] = { "32 39 5 1", ". c none", "+ c black", "@ c #3070E0", "# c #F05050", "$ c #35E035", "................+...............", "..............+++++.............", "............+++++@@++...........", "..........+++++@@@@@@++.........", "........++++@@@@@@@@@@++........", "......++++@@++++++++@@@++.......", ".....+++@@@+++++++++++@@@++.....", "...+++@@@@+++@@@@@@++++@@@@+....", "..+++@@@@+++@@@@@@@@+++@@@@@++..", ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++", ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+", ".+##++@@@@+++@@@+++++@@@@@@@@$@.", ".+###++@@@@+++@@@+++@@@@@++$$$@.", ".+####+++@@@+++++++@@@@@+@$$$$@.", ".+#####+++@@@@+++@@@@++@$$$$$$+.", ".+######++++@@@@@@@++@$$$$$$$$+.", ".+#######+##+@@@@+++$$$$$$@@$$+.", ".+###+++##+##+@@++@$$$$$$++$$$+.", ".+###++++##+##+@@$$$$$$$@+@$$@+.", ".+###++++++#+++@$$@+@$$@++$$$@+.", ".+####+++++++#++$$@+@$$++$$$$+..", ".++####++++++#++$$@+@$++@$$$$+..", ".+#####+++++##++$$++@+++$$$$$+..", ".++####+++##+#++$$+++++@$$$$$+..", ".++####+++####++$$++++++@$$$@+..", ".+#####++#####++$$+++@++++@$@+..", ".+#####++#####++$$++@$$@+++$@@..", ".++####++#####++$$++$$$$$+@$@++.", ".++####++#####++$$++$$$$$$$$+++.", ".+++####+#####++$$++$$$$$$$@+++.", "..+++#########+@$$+@$$$$$$+++...", "...+++########+@$$$$$$$$@+++....", ".....+++######+@$$$$$$$+++......", "......+++#####+@$$$$$@++........", ".......+++####+@$$$$+++.........", ".........++###+$$$@++...........", "..........++##+$@+++............", "...........+++++++..............", ".............++++..............."}; |
2 則留言