(2017.10.27 追加記事;
gtk2,gtk3 でメニューを表示します。(Gtk::UIManagerGtk::MenuBar

ここではメニューバーを作っていきます。
メニューの作り方はいくつかありますが、A.UIマネージャを使う方法と、B.手作業で作っていく方法があります。(アイテムファクトリを使う方法は非推奨になっています。)

→・UIマネージャを使うRuby/GTK2 チュートリアル
→・手作業でのメニュー作成Ruby/GTK2 チュートリアル
→・Dynamic Menu CreationMenus and ToolbarsRuby-GNOME2 Tutorials
→・Menu BarsRuby/GTK2 Tutorial
→・Ruby Gtk メニュー - いち雑記
→・GTK Programming in Ruby (4) - Adding Menubar, using UIManager - Socrateos


A.UIマネージャを使う方法(Gtk::UIManager
メニューの構成をXMLで書き、対応するアクションを作ったら Gtk::ActionGroup、Gtk::UIManager に登録します。

1.メニュー構成をXMLで作成
 別ファイルにしても、同じファイル内で変数に代入しても構いません
 書き方)
 →・UIマネージャを使う - Ruby/GTK2 チュートリアル
 →・Dynamic Menu Creation - Menus and Toolbars - Ruby-GNOME2 Tutorials


2.アクションを作成
 XMLで定義したアクションに対応するメニュー名、動作などを作成します
 書き方は 3. の entries を参照


3.Gtk::ActionGroup にアクションを登録
○ Gtk::ActionGroup.new(name)
 ActionGroupを作成します

○ Gtk::ActionGroup#add_actions(entries)
 アクション(Gtk::ActionGtk::MenuItem)を登録します
・entries; [[name, stock_id, label, accelerator, tooltip, proc], ... ];各アクションを配列形式で登録
 - name;XMLで定義したアクション名
 - stock_id;Gtk::Stock に登録されているアイコン名(アイコン画像が用意されていない場合は無視)
 - label;表示させたいメニュー名
 - accelerator;キーボードショートカット;形式は Gtk::Accelerator.parse 参照("<control>R" など)
 - tooltip;アイコン上のマウスオーバーレイ表示(メニューバーでは表示されません)
 - proc;メニューが選択された場合の動作を Procで(注意;gtk3では、proc は省略できません)
  引数は2つ;第1引数 Gtk::ActionGroup,第2引数 Gtk::Action
  例)proc = Proc.new { |actiongroup, action| ... } 
 
○ Gtk::ActionGroup#add_toggle_actions(entries)
 トグルアクション(Gtk::ToggleActionGtk::CheckMenuItem)を登録します
・entries: [[name, stock_id, label, accelerator, tooltip, proc, is_active], ... ];各アクションを配列形式で登録
 - name;XMLで定義したアクション名
 - stock_id;Gtk::Stock に登録されているアイコン名(アイコン画像が用意されていない場合は無視)
 - label;表示させたいメニュー名
 - accelerator;キーボードショートカット;形式は Gtk::Accelerator.parse 参照("<control>R" など)
 - tooltip;アイコン上のマウスオーバーレイ表示(メニューバーでは表示されません)
 - proc;メニューが選択された場合の動作を Procで(注意;gtk3では、proc は省略できません)
  引数は2つ;第1引数 Gtk::ActionGroup,第2引数 Gtk::Action
  例)proc = Proc.new { |actiongroup, action| ... } 
 - is_active;トグルアクションの初期値(true 又は false)

Gtk::ActionGroup#add_radio_actions(entries, default_value) {|action, current| ... }
 ラジオアクション(Gtk::RadioActionGtk::RadioMenuItem)を登録します
・entries: [[name, stock_id, label, accelerator, tooltip, value], ... ];各アクションを配列形式
 - name;XMLで定義したアクション名
 - stock_id;Gtk::Stock に登録されているアイコン名(アイコン画像が用意されていない場合は無視)
 - label;表示させたいメニュー名
 - accelerator;キーボードショートカット;形式は Gtk::Accelerator.parse 参照("<control>R" など)
 - tooltip;アイコン上のマウスオーバーレイ表示(メニューバーでは表示されません)
 - value;各ラジオアクションを区別するための番号
default_value;デフォルトで選択されているラジオアクションの番号
{ |action, current| 処理 };選択された場合の動作をブロックで記述
 - action;前回の Gtk::Action
 - current;現在の Gtk::Action
 - 処理;処理を書きます

gtk3では、ラジオアクションの動作がうまくいきません(選択したラジオアクションに切り替わらない)
→・[gtk3] Gtk/ActionGroup#add_radio_actions have a problem using UIManager in MenuBar ・ Issue #1086 - ruby-gnome2/ruby-gnome2 - GitHub


4.Gtk::UIManager に登録
Gtk::UIManager.new
 UIマネージャを作ります

Gtk::UIManager#add_ui(filename)
Gtk::UIManager#add_ui(buffer)
 メニュー構成(XML)を UIManager に登録します
 ・filename;XMLファイルのファイル名
 ・buffer;XMLファイルの変数名

Gtk::UIManager#insert_action_group(action_group, pos)
 ActionGroupを UIManager に登録します 
 ・action_group: Gtk::ActionGroup
 ・pos: 登録される場所?(ほとんどの場合 0 でいいみたいです)

Gtk::UIManager#get_widget(path)
 登録したメニューウィジェットを呼び出します
 (メニューバー、ツールバー、ポップアップメニューなどを各々個別に貼り付けるため)
 ・path;XMLで記述したメニュー名を文字列で(例;"/MenuBar")


(license; public domain)
・gtk_menu_1.xml
<?xml version="1.0"?>
<ui>
  <menubar name="MenuBar">
    <menu name="FileMenu" action="FileAction">
      <menuitem name="FileNew" action="NewAction"/>
      <menuitem name="FileOpen" action="OpenAction"/>
      <separator />
      <menuitem name="FileQuit" action="QuitAction"/>
    </menu>
    <menu name="OptionMenu" action="OptionAction">
      <menuitem name="OptionItalic" action="ItalicAction"/>
      <separator />
      <menu name="ColorMenu" action="ColorAction">
        <menuitem name="ColorRed" action="RedAction"/>
        <menuitem name="ColorGreen" action="GreenAction"/>
        <menuitem name="ColorBlue" action="BlueAction"/>
      </menu>
    </menu>
  </menubar>
</ui>
 
・gtk_menu_1.rb
require 'gtk2'
#require 'gtk3'      # gtk3ライブラリでも実行可能(ただし、ラジオメニューの動作が異常)

window = Gtk::Window.new
window.set_size_request(400, 300)

# メニューバーをUIManagerで作る
# メニューの構成(User Interface)をXMLで記述
# XMLは別ファイルにするか、同じファイル内で変数にする
# nameはmenubar以外は省略可
# 同じディレクトリに gtk_menu_1.xml を置く


# メニュー選択時の処理(Proc);引数|actiongroup, action|
nil_call  = Proc.new {  }
proc_call = Proc.new do |actiongroup, action|
  puts "#{actiongroup.name}: '#{action.name}' is called."
end
quit_call   = Proc.new { Gtk.main_quit }
toggle_call = Proc.new do |actiongroup, action|
  puts "#{actiongroup.name}: #{action.name}? #{action.active?}"
end

# ActionGroupに登録するアクション(配列)
# [menu_uiのアクション名,
#  Stock ID(登録アイコン),
#  表示メニュー名,
#  Accelerator(ショートカット),
#  tooltip(アイコン上のマウスオーバーレイ表示),
#  処理(Proc)]
# 注;tooltipはメニューバーでは表示されない
# 注;gtk3では、処理(Proc)は省略できない)
menu_actions = [
  ["FileAction"  ,              nil, "ファイル" ,          nil, "File"  ,  nil_call],
  ["NewAction"   , Gtk::Stock::NEW , "新規(N)"  , "<control>N", "New"   , proc_call],
  ["OpenAction"  , Gtk::Stock::OPEN, "開く(O)"  , "<control>O", "Open"  , proc_call],
  ["QuitAction"  , Gtk::Stock::QUIT, "終了(Q)"  , "<control>Q", "Quit"  , quit_call],
  ["OptionAction",              nil, "オプション",          nil, "Option",  nil_call],
  ["ColorAction" ,              nil, "カラー"   ,          nil, "Color" ,  nil_call],
]

# トグルメニューのアクション
# [menu_uiのアクション名,
#  Stock ID(登録アイコン),
#  表示メニュー名,
#  Accelerator(ショートカット),
#  tooltip(アイコン上のマウスオーバーレイ表示),
#  処理(Proc),
#  is_active(初期状態;true or false)]
# 注;tooltipはメニューバーでは表示されない
toggle_action = [
  ["ItalicAction", nil, "イタリック", "<control>I", "Italic", toggle_call, false]
]

# ラジオメニューのアクション
# [menu_uiのアクション名,
#  Stock ID(登録アイコン),
#  表示メニュー名,
#  Accelerator(ショートカット),
#  tooltip(アイコン上のマウスオーバーレイ表示),
#  value(各ラジオメニューを指定する整数)]
# 注;tooltipはメニューバーでは表示されない
color_radio_actions = [
  ["RedAction", nil, "レッド", "<control>R", "Red", 0],
  ["GreenAction", nil, "グリーン", "<control>G", "Green", 1],
  ["BlueAction", nil, "ブルー", "<control>B", "Blue", 2]
]


# ActionGroupにアクションを登録
action_group = Gtk::ActionGroup.new("menubar_action")
action_group.add_actions(menu_actions)
action_group.add_toggle_actions(toggle_action)

#add_radio_actions(ラジオメニューのアクション, デフォルトで選択されているラジオメニューのvalue)
action_group.add_radio_actions(color_radio_actions, 1) do |action, current|
  puts "previous is '#{action.name}', current is '#{current.name}'."
end

# UIManagerにActionグループ、ショートカット、UIを登録
uimanager = Gtk::UIManager.new
uimanager.insert_action_group(action_group, 0)
window.add_accel_group(uimanager.accel_group)
uimanager.add_ui("./gtk_menu_1.xml")

menubar = uimanager.get_widget("/MenuBar")
menubar.set_size_request(400, -1)


text_area = Gtk::TextView.new
text_area.set_size_request(150, 200)
text_area.buffer.text = 'Hello World!'

fixed = Gtk::Fixed.new
fixed.put(menubar, 0, 0)
fixed.put(text_area, 20, 60)
window.add(fixed)

window.show_all
window.signal_connect("destroy") { Gtk.main_quit }
Gtk.main

gtk_menu_1

gtk_menu_1_term


・gtk_menu_2.rb
require 'gtk3'       # gtk3では、ラジオメニューの動作が異常
#require 'gtk2'      # gtk2ライブラリでも実行可能

window = Gtk::Window.new
window.set_size_request(400, 300)

# メニューバーをUIManagerで作る
# メニューの構成(User Interface)をXMLで記述
# (XMLは別ファイルにしても可)
# nameはmenubar以外は省略可
menu_ui = %Q[
<ui>
  <menubar name="MenuBar">
    <menu name="FileMenu" action="FileAction">
      <menuitem name="FileNew" action="NewAction"/>
      <menuitem name="FileOpen" action="OpenAction"/>
      <separator />
      <menuitem name="FileQuit" action="QuitAction"/>
    </menu>
    <menu name="OptionMenu" action="OptionAction">
      <menuitem name="OptionItalic" action="ItalicAction"/>
      <separator />
      <menu name="ColorMenu" action="ColorAction">
        <menuitem name="ColorRed" action="RedAction"/>
        <menuitem name="ColorGreen" action="GreenAction"/>
        <menuitem name="ColorBlue" action="BlueAction"/>
      </menu>
    </menu>
  </menubar>
</ui>
]


# メニュー選択時の処理(Proc);引数|actiongroup, action|
nil_call  = Proc.new {  }
proc_call = Proc.new do |actiongroup, action|
  puts "#{actiongroup.name}: '#{action.name}' is called."
end
quit_call   = Proc.new { Gtk.main_quit }
toggle_call = Proc.new do |actiongroup, action|
  puts "#{actiongroup.name}: #{action.name}? #{action.active?}"
end

# ActionGroupに登録するアクション(配列)
# [menu_uiのアクション名,
#  Stock ID(登録アイコン),
#  表示メニュー名,
#  Accelerator(ショートカット),
#  tooltip(アイコン上のマウスオーバーレイ表示),
#  処理(Proc)]
# 注;tooltipはメニューバーでは表示されない
# 注;gtk3では、処理(Proc)は省略できない)
menu_actions = [
  ["FileAction"  ,              nil, "ファイル" ,          nil, "File"  ,  nil_call],
  ["NewAction"   , Gtk::Stock::NEW , "新規(N)"  , "<control>N", "New"   , proc_call],
  ["OpenAction"  , Gtk::Stock::OPEN, "開く(O)"  , "<control>O", "Open"  , proc_call],
  ["QuitAction"  , Gtk::Stock::QUIT, "終了(Q)"  , "<control>Q", "Quit"  , quit_call],
  ["OptionAction",              nil, "オプション",          nil, "Option",  nil_call],
  ["ColorAction" ,              nil, "カラー"   ,          nil, "Color" ,  nil_call],
]

# トグルメニューのアクション
# [menu_uiのアクション名,
#  Stock ID(登録アイコン),
#  表示メニュー名,
#  Accelerator(ショートカット),
#  tooltip(アイコン上のマウスオーバーレイ表示),
#  処理(Proc),
#  is_active(初期状態;true or false)]
# 注;tooltipはメニューバーでは表示されない
toggle_action = [
  ["ItalicAction", nil, "イタリック", "<control>I", "Italic", toggle_call, false]
]

# ラジオメニューのアクション
# [menu_uiのアクション名,
#  Stock ID(登録アイコン),
#  表示メニュー名,
#  Accelerator(ショートカット),
#  tooltip(アイコン上のマウスオーバーレイ表示),
#  value(各ラジオメニューを指定する整数)]
# 注;tooltipはメニューバーでは表示されない
color_radio_actions = [
  ["RedAction", nil, "レッド", "<control>R", "Red", 0],
  ["GreenAction", nil, "グリーン", "<control>G", "Green", 1],
  ["BlueAction", nil, "ブルー", "<control>B", "Blue", 2]
]


# ActionGroupにアクションを登録
action_group = Gtk::ActionGroup.new("menubar_action")
action_group.add_actions(menu_actions)
action_group.add_toggle_actions(toggle_action)

#add_radio_actions(ラジオメニューのアクション, デフォルトで選択されているラジオメニューのvalue)
action_group.add_radio_actions(color_radio_actions, 1) do |action, current|
  puts "previous is '#{action.name}', current is '#{current.name}'."
end

# UIManagerにActionグループ、ショートカット、UIを登録
uimanager = Gtk::UIManager.new
uimanager.insert_action_group(action_group, 0)
window.add_accel_group(uimanager.accel_group)
uimanager.add_ui(menu_ui)
# XMLファイルが別ファイル gtk_menu_1.xml の場合は;
# uimanager.add_ui("./gtk_menu_1.xml") 

menubar = uimanager.get_widget("/MenuBar")
menubar.set_size_request(400, -1)


text_area = Gtk::TextView.new
text_area.set_size_request(150, 200)
text_area.buffer.text = 'Hello World!'

fixed = Gtk::Fixed.new
fixed.put(menubar, 0, 0)
fixed.put(text_area, 20, 60)
window.add(fixed)

window.show_all
window.signal_connect("destroy") { Gtk.main_quit }
Gtk.main

gtk_menu_2


gtk_menu_2_term

(gtk3 ではラジオアクションの動作が異常)