手動でメニューバーを作る

概要

メニューバーを手動で作成して表示する。

UIマネージャ経由でメニューを作る方が楽であるが、状況に応じてメニュー項目を変えたい場合は手動で作成した方が柔軟性があって良い。

はじめにGtk::MenuBarを作成し、大項目( Gtk::MenuItem )を挿入する。次に表示させるメニュー( Gtk::Menu ) を作成して 大項目に挿入する。さらにメニューに表示させる項目( Gtk::MenuItem )をメニューに挿入する。若干ややこしいが まとめるとGtk::MenuBar、Gtk::MenuItem、Gtk::Menu は次のような親子関係になる

Gtk::MenuBar ←( append )- Gtk::MenuItem ←( set_submenu )- Gtk::Menu ←( append )- Gtk::MenuItem ←( set_submenu )- Gtk::Menu ・・・

なお下の例ではGtk::MenuItemを直接作るのではなくてアクショングループからアクションを取得して create_menu_item()により Gtk::MenuItemを作成している。

ソース

menubar.cpp

#include <gtkmm.h>
#include <iostream>

class MainWin : public Gtk::Window
{
    Gtk::VBox m_box;
    Glib::RefPtr< Gtk::ActionGroup > m_actiongroup;

public:
    MainWin();

private:
    void on_menu_test1(){ std::cout << "test1\n"; }
    void on_menu_test2() { std::cout << "test2\n"; }
};


MainWin::MainWin()
{
    // OFFになってるイベントを追加
    add_events( Gdk::BUTTON_PRESS_MASK );

    // アクショングループの作成とアクション登録
    m_actiongroup = Gtk::ActionGroup::create();
    m_actiongroup->add( Gtk::Action::create( "TestMenu1", Gtk::Stock::QUIT ),
                        sigc::mem_fun( *this, &MainWin::on_menu_test1 ) );    
    m_actiongroup->add( Gtk::Action::create( "TestMenu2", "テスト2" ),
                        Gtk::AccelKey( 'a', Gdk::CONTROL_MASK ), 
                        sigc::mem_fun( *this, &MainWin::on_menu_test2 ) );    

    // メニューバー作成とパッキング
    Gtk::MenuBar* menubar = Gtk::manage( new Gtk::MenuBar() );
    m_box.pack_start( *menubar, Gtk::PACK_SHRINK );
    add( m_box );

    // メニュー項目を作成してバーに挿入
    Gtk::MenuItem* menuitem = Gtk::manage( new Gtk::MenuItem( "メニュー1" ) );
    menubar->append( *menuitem );

    // サブメニューを作成してメニュー項目に挿入
    Gtk::Menu* submenu = Gtk::manage( new Gtk::Menu() );
    menuitem->set_submenu( *submenu );

    // サブメニューの中の項目作成
    // アクセルグループをセットしないと assertion が出る
    Glib::RefPtr< Gtk::Action > action;
    ( action = m_actiongroup->get_action( "TestMenu1" ) )->set_accel_group( get_accel_group() ); 
    submenu->append( *Gtk::manage( action->create_menu_item() ) );

    ( action = m_actiongroup->get_action( "TestMenu2" ) )->set_accel_group( get_accel_group() ); 
    submenu->append( *Gtk::manage( action->create_menu_item() ) );

    // 別のメニュー項目作成
    menuitem = Gtk::manage( new Gtk::MenuItem( "メニュー2" ) );
    menubar->append( *menuitem );

    resize( 300, 300 );
    show_all_children();
}


int main( int argc, char *argv[] )
{
    Gtk::Main kit( argc, argv );
    MainWin mainwin;
    Gtk::Main::run( mainwin );

    return 0;
}


コンパイル

必要なコンパイルオプションは pkg-config を使って取得する。

g++ menubar2.cpp -o menubar2 `pkg-config gtkmm-2.4 --cflags --libs`

結果