メニューバー


第7章で扱ったメニューバーを、もう少し使ってみる。

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

static void cb_quit(GtkWidget *widget, gpointer data)
{
  gtk_main_quit();
}

static GtkWidget* create_menu(void)
{
  GtkWidget *menubar;
  GtkWidget *menu;
  GtkWidget *item;
  GtkWidget *image;
  GtkAccelGroup *accel_group;
  GSList *group = NULL;

  //メニューバーを生成
  menubar = gtk_menu_bar_new();
  accel_group = gtk_accel_group_new();

  //メニューバーに親メニューFileを追加
  item = gtk_menu_item_new_with_mnemonic("_File");
  gtk_container_add(GTK_CONTAINER(menubar), item);
  menu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
  {
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Fileに子メニューNewを追加
    item = gtk_menu_item_new_with_mnemonic("_New");
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Fileに子メニューOpenを追加
    item = gtk_menu_item_new_with_mnemonic("_Open");
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Fileに子メニューSaveを追加
    item = gtk_menu_item_new_with_mnemonic("_Save");
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Fileに子メニューSace asを追加
    item = gtk_menu_item_new_with_mnemonic("Save _as");
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_separator_menu_item_new();
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Fileに子メニューQuitを追加
    item = gtk_menu_item_new_with_mnemonic("_Quit");
    gtk_container_add(GTK_CONTAINER(menu), item);
    g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(cb_quit), NULL);
  }
  //メニューバーに親メニューEditを追加
  item = gtk_menu_item_new_with_mnemonic("_Edit");
  gtk_container_add(GTK_CONTAINER(menubar), item);
  menu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
  {
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Editに子メニューCutを追加
    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CUT, accel_group);
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Editに子メニューCopyを追加
    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY, accel_group);
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Editに子メニューPasteを追加
    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE, accel_group);
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Editに子メニューDeleteを追加
    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, accel_group);
    gtk_container_add(GTK_CONTAINER(menu), item);
  }
  //メニューバーに親メニューViewを追加
  item = gtk_menu_item_new_with_mnemonic("_View");
  gtk_container_add(GTK_CONTAINER(menubar), item);
  menu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
  {
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Viewに子メニューShow Hidden Foldersを追加
    item = gtk_check_menu_item_new_with_label("Show Hidden Folders");
    gtk_container_add(GTK_CONTAINER(menu), item);

    //Viewに子メニューSort by ...を追加
    item = gtk_image_menu_item_new_with_label("Sort by ...");
    image = gtk_image_new_from_stock(GTK_STOCK_SORT_ASCENDING, GTK_ICON_SIZE_MENU);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
    gtk_container_add(GTK_CONTAINER(menu), item);
    menu = gtk_menu_new();
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
    {
      //Sort by ...にラジオメニューFile typeを追加
      item = gtk_radio_menu_item_new_with_label(group, "File type");
      gtk_container_add(GTK_CONTAINER(menu), item);
      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);

      //Sort by ...にラジオメニューFile sizeを追加
      group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
      item = gtk_radio_menu_item_new_with_label(group, "File size");
      gtk_container_add(GTK_CONTAINER(menu), item);

      //Sort by ...にラジオメニューUpdate timeを追加
      group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
      item = gtk_radio_menu_item_new_with_label(group, "Update time");
      gtk_container_add(GTK_CONTAINER(menu), item);
    }
  }
  return menubar;
}

int main(int argc, char** argv)
{
  GtkWidget *window;
  GtkWidget *menubar;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "Menubar");
  gtk_widget_set_size_request(window, 300, -1);
  gtk_container_set_border_width(GTK_CONTAINER(window), 5);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  menubar = create_menu();
  gtk_container_add(GTK_CONTAINER(window), menubar);

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

今回はメニューの構成を少し増やしてみた。

FileEditView
├New├Cut├Show Hidden Folders
├Open├Copy└Sort by ...┬File type
├Save├Paste├File size
├Save as└Delete└Update time
└Quit

なお、シグナルの処理を施したのはQuitのみである。

Viewの子メニューにイメージメニュー、Sort by ...の子メニューにラジオメニューを使用してみた。


ポップアップメニュー


ウィンドウ内を右クリックすると現れる、ポップアップメニューを作ってみる。

#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

static void cb_quit(GtkWidget *widget, gpointer data)
{
  gtk_main_quit();
}

static gboolean cb_popup_menu(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
{
  GtkMenu *popupmenu = GTK_MENU(user_data);

  if(event->button == 3){
//右クリック

    gtk_menu_popup(popupmenu, NULL, NULL, NULL, NULL, 0, event->time);
  }
  return FALSE;
}

static GtkWidget* create_popupmenu(GtkWindow *parent)
{
  GtkWidget *popupmenu;
  GtkWidget *menu;
  GtkWidget *item;
  GtkWidget *image;
  GtkAccelGroup *accel_group;
  GSList *group = NULL;

  popupmenu = gtk_menu_new();
  accel_group = gtk_accel_group_new();
  gtk_window_add_accel_group(parent, accel_group);

  item = gtk_menu_item_new_with_label("Popup Menu");
  gtk_widget_set_sensitive(item, FALSE);
  gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), item);

  item = gtk_separator_menu_item_new();
  gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), item);

  item = gtk_menu_item_new_with_mnemonic("_File");
  gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), item);
  menu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
  {
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_menu_item_new_with_mnemonic("_New");
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_menu_item_new_with_mnemonic("_Open");
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_menu_item_new_with_mnemonic("_Save");
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_menu_item_new_with_mnemonic("Save _as");
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_separator_menu_item_new();
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_menu_item_new_with_mnemonic("_Quit");
    gtk_container_add(GTK_CONTAINER(menu), item);
    g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(cb_quit), NULL);
  }
  item = gtk_menu_item_new_with_mnemonic("_Edit");
  gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), item);
  menu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
  {
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CUT, accel_group);
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_COPY, accel_group);
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_PASTE, accel_group);
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, accel_group);
    gtk_container_add(GTK_CONTAINER(menu), item);
  }
  item = gtk_menu_item_new_with_mnemonic("_View");
  gtk_menu_shell_append(GTK_MENU_SHELL(popupmenu), item);
  menu = gtk_menu_new();
  gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
  {
    item = gtk_menu_item_new();
    gtk_container_add(GTK_CONTAINER(menu), item);

    item = gtk_image_menu_item_new_with_label("Sort by ...");
    image = gtk_image_new_from_stock(GTK_STOCK_SORT_ASCENDING, GTK_ICON_SIZE_MENU);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
    gtk_container_add(GTK_CONTAINER(menu), item);
    menu = gtk_menu_new();
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
    {
      item = gtk_radio_menu_item_new_with_label(group, "File type");
      gtk_container_add(GTK_CONTAINER(menu), item);
      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);

      group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
      item = gtk_radio_menu_item_new_with_label(group, "File size");
      gtk_container_add(GTK_CONTAINER(menu), item);

      group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item));
      item = gtk_radio_menu_item_new_with_label(group, "Update time");
      gtk_container_add(GTK_CONTAINER(menu), item);
    }
  }
  return popupmenu;
}

int main(int argc, char** argv)
{
  GtkWidget *window;
  GtkWidget *eventbox;
  GtkWidget *popupmenu;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "PopupMenu");
  gtk_container_set_border_width(GTK_CONTAINER(window), 5);
  gtk_widget_set_size_request(window, 300, 100);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  popupmenu = create_popupmenu(GTK_WINDOW(window));
  gtk_widget_show_all(popupmenu);

  eventbox = gtk_event_box_new();
  gtk_container_add(GTK_CONTAINER(window), eventbox);
  g_signal_connect(G_OBJECT(eventbox), "button_press_event", G_CALLBACK(cb_popup_menu), popupmenu);

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

Print Screenが使えないので、図説ができない。 メニューの構成はメニューバーと同じである。


UIManager


第7章の復習である。

#include <gtk/gtk.h>

static void cb_new(void)
{
  g_print("new:\n");
}

static void cb_open(GtkWidget *widget, gpointer user_data)
{
  g_print( "open:%s\n", (gchar*)user_data );
}

static const gchar *menu_info =
"<ui>"
" <menubar name='Menubar'>"
" <menu action='FileMenu'>"
" <menuitem action='New'/>"
" <menuitem action='Open'/>"
" <menuitem action='Save'/>"
" <menuitem action='SaveAs'/>"
" <separator/>"
" <menuitem action='Quit'/>"
" </menu>"
" <menu action='EditMenu'>"
" <menuitem action='Cut'/>"
" <menuitem action='Copy'/>"
" <menuitem action='Paste'/>"
" <menuitem action='Delete'/>"
" </menu>"
" <menu action='ViewMenu'>"
" <menuitem action='ShowHidden'/>"
" <menu action='SortMenu'>"
" <menuitem action='FileType'/>"
" <menuitem action='FileSize'/>"
" <menuitem action='UpdateTime'/>"
" </menu>"
" </menu>"
" </menubar>"
"</ui>";

static GtkActionEntry entries[] = {
  {"FileMenu", NULL, "_File"},
  {"EditMenu", NULL, "_Edit"},
  {"ViewMenu", NULL, "_View"},
  {"SortMenu", GTK_STOCK_SORT_ASCENDING, "Sort by ..."},
  {"New", NULL, "_New", "<control>N", NULL, G_CALLBACK(cb_new)},
  {"Open", NULL, "_Open", "<control>O", NULL, G_CALLBACK(cb_open)},
  {"Save", NULL, "_Save", "<control>S", NULL, NULL},
  {"SaveAs", NULL, "Save _as", "<shift><control>S", NULL, NULL},
  {"Quit", NULL, "_Quit", "<control>Q", NULL, gtk_main_quit},
  {"Cut", GTK_STOCK_CUT, "C_ut", "<control>X", NULL, NULL},
  {"Copy", GTK_STOCK_COPY, "_Copy", "<control>C", NULL, NULL},
  {"Paste", GTK_STOCK_PASTE, "_Paste", "<control>V", NULL, NULL},
  {"Delete", GTK_STOCK_DELETE, "_Delete", "<control>D", NULL, NULL}
};

static GtkToggleActionEntry toggle_entries[] =
{
  {"ShowHidden", NULL, "Show Hidden Folders", "<control>H", NULL, NULL, FALSE}
};

enum
{
  SORT_FILE_TYPE,
  SORT_FILE_SIZE,
  SORT_UPDATE_TIME
};

static GtkRadioActionEntry radio_entries[] =
{
  {"FileType", NULL, "File type", NULL, NULL, SORT_FILE_TYPE},
  {"FileSize", NULL, "File size", NULL, NULL, SORT_FILE_SIZE},
  {"UpdateTime", NULL, "Update time", NULL, NULL, SORT_UPDATE_TIME}
};

static void activate_radio_action(GtkAction *action, GtkRadioAction *current)
{
  g_print( "Radio action %s selected\n", gtk_action_get_name(GTK_ACTION(current)) );
}

static guint n_entries = G_N_ELEMENTS(entries);
static guint n_toggle_entries = G_N_ELEMENTS(toggle_entries);
static guint n_radio_entries = G_N_ELEMENTS(radio_entries);

static GtkUIManager* create_menu(GtkWidget *parent)
{
  GtkUIManager *ui;
  GtkActionGroup *actions;
  GError *gErrors = NULL;
  ui = gtk_ui_manager_new();
  actions = gtk_action_group_new("menu");
  gtk_action_group_add_actions(actions, entries, n_entries, parent);
  gtk_action_group_add_toggle_actions(actions, toggle_entries, n_toggle_entries, NULL);
  gtk_action_group_add_radio_actions(actions, radio_entries, n_radio_entries, SORT_FILE_TYPE, G_CALLBACK(activate_radio_action), NULL);
  gtk_ui_manager_insert_action_group(ui, actions, 0);
  gtk_ui_manager_add_ui_from_string(ui, menu_info, -1, NULL);
  gtk_window_add_accel_group(GTK_WINDOW(parent), gtk_ui_manager_get_accel_group(ui));
  return ui;
}

int main(int argc, char** argv)
{
  GtkWidget *window;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "UIManager");
  gtk_widget_set_size_request(window, 300, -1);
  gtk_container_set_border_width(GTK_CONTAINER(window), 5);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

  GtkUIManager *ui;
  GtkWidget *menubar;

  ui = create_menu(window);
  g_object_set_data(G_OBJECT(window), "ui", (gpointer)ui);
  menubar = gtk_ui_manager_get_widget(ui, "/Menubar");
  gtk_container_add(GTK_CONTAINER(window), menubar);

  gtk_widget_show_all(window);
  gtk_main();

  return 0;
}

一応、上記2つと同じ構成のメニューを作成できた。 Quitの他にNewとOpenだけ、簡単な動作を入れてみた。


前章  | 目次 |  次章



トップ



/