GTK+ 2.0 教學-工具欄 Toolbar

工具欄(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_HORIZONTALGTK_ORIENTATION_VERTICALstyle參數用於設置工具欄項的外觀,可以取GTK_TOOLBAR_ICONSGTK_TOOLBAR_TEXTGTK_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_SPACEGTK_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",
"................+...............",
"..............+++++.............",
"............+++++@@++...........",
"..........+++++@@@@@@++.........",
"........++++@@@@@@@@@@++........",
"......++++@@++++++++@@@++.......",
".....+++@@@+++++++++++@@@++.....",
"...+++@@@@+++@@@@@@++++@@@@+....",
"..+++@@@@+++@@@@@@@@+++@@@@@++..",
".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
".+##++@@@@+++@@@+++++@@@@@@@@$@.",
".+###++@@@@+++@@@+++@@@@@++$$$@.",
".+####+++@@@+++++++@@@@@+@$$$$@.",
".+#####+++@@@@+++@@@@++@$$$$$$+.",
".+######++++@@@@@@@++@$$$$$$$$+.",
".+#######+##+@@@@+++$$$$$$@@$$+.",
".+###+++##+##+@@++@$$$$$$++$$$+.",
".+###++++##+##+@@$$$$$$$@+@$$@+.",
".+###++++++#+++@$$@+@$$@++$$$@+.",
".+####+++++++#++$$@+@$$++$$$$+..",
".++####++++++#++$$@+@$++@$$$$+..",
".+#####+++++##++$$++@+++$$$$$+..",
".++####+++##+#++$$+++++@$$$$$+..",
".++####+++####++$$++++++@$$$@+..",
".+#####++#####++$$+++@++++@$@+..",
".+#####++#####++$$++@$$@+++$@@..",
".++####++#####++$$++$$$$$+@$@++.",
".++####++#####++$$++$$$$$$$$+++.",
".+++####+#####++$$++$$$$$$$@+++.",
"..+++#########+@$$+@$$$$$$+++...",
"...+++########+@$$$$$$$$@+++....",
".....+++######+@$$$$$$$+++......",
"......+++#####+@$$$$$@++........",
".......+++####+@$$$$+++.........",
".........++###+$$$@++...........",
"..........++##+$@+++............",
"...........+++++++..............",
".............++++..............."};

感謝你看到這裡,很快就可以離開了,但最好的獎勵行動就是按一下幫我分享或留言,感恩喔~

點我分享到Facebook

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *