pygtkで遊ぼう(13) メニューバーで階層メニュー 編
最近作っているファイルコピーツールのメニューをいじっていて、「そういえば、サブメニューのあるメニューバーって作ったことないな。。」ということに気づきました。
以前、pygtkで遊ぼう(6) メニュー編 でメニューバーについて書きました。
その時のメニューバーは単純なメニューバーで、サブメニューのあるメニュー項目のないものでした。
今回は、その時作ったサンプルを拡張して、サブメニューのあるメニューバーにしてみました。
ソースコードはこんな感じです。
# -*- coding: utf-8 -*- import sys import pygtk if sys.platform != 'win32': pygtk.require('2.0') import gtk # # class simpleWindow: ''' テスト用ウインドウ ''' def __init__(self): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_border_width(2) self.window.set_size_request(400, 300) self.window.connect('delete_event', self.on_quit) vbox = gtk.VBox() menubar = self.get_main_menu() vbox.pack_start(menubar, False, False, 0) layout = gtk.Layout() vbox.pack_start(layout) self.window.add(vbox) self.window.show_all() gtk.main() def get_main_menu(self): ''' メインメニュー構築処理 ''' ## メニューバーの定義 mainMenu = '''''' # UIManagerインスタンスの再生 uimgr = gtk.UIManager() # アクセラレータグループをウインドウに追加 acclgrp = uimgr.get_accel_group() self.window.add_accel_group(acclgrp) # アクショングループの作成 actgrpBase = gtk.ActionGroup('MenuActionBase') actgrpBase.add_actions([('Normal Menu', None, '_Normal Menu'), ('Toggle Menu', None, '_Toggle Menu'), ('Radio Menu', None, '_Radio Menu'), ('PlaceHolders', None, '_PlaceHolders'), ('Normal setting', None, '_Normal setting'), ('Toggle setting', None, '_Toggle setting'), ('Radio setting', None, '_Radio setting')]) uimgr.insert_action_group(actgrpBase, 0) # ノーマルメニューアクションの登録 actgrpBase.add_actions([('normal item 1', None, 'item _1', None, 'sample item for normal menu action', self.on_normal_item1), ('normal item 2', None, 'item _2', None, 'sample item for normal menu action', self.on_normal_item2)]) # トグルメニューアクションの登録 actgrpBase.add_toggle_actions([('toggle item 1', None, 'item _1', None, 'sample item for toggle menu action', self.on_toggle_item1, True), ('toggle item 2', None, 'item _2', None, 'sample item for toggle menu action', self.on_toggle_item2, True)]) # Modeメニューアクションの登録 actgrpBase.add_radio_actions([('radio item 1', None, 'item _1', None, 'sample item for radio menu action', 0), ('radio item 2', None, 'item _2', None, 'sample item for radio menu action', 1)], 0, self.on_radio_menu_changed) # PlaceHoldersメニューアクションの登録 actgrpBase.add_actions([('normal holder item 1', None, 'holder item _1', None, 'sample item for normal sub menu action', self.on_normal_holder_item1), ('normal holder item 2', None, 'holder item _2', None, 'sample item for normal sub menu action', self.on_normal_holder_item2)]) actgrpBase.add_toggle_actions([('toggle holder item 1', None, 'holder item _1', None, 'sample item for toggle menu action', self.on_toggle_holder_item1, True), ('toggle holder item 2', None, 'holder item _2', None, 'sample item for toggle menu action', self.on_toggle_holder_item2, True)]) actgrpBase.add_radio_actions([('radio holder item 1', None, 'holder item _1', None, 'sample item for radio menu action', 0), ('radio holder item 2', None, 'holder item _2', None, 'sample item for radio menu action', 1)], 0, self.on_radio_holder_menu_changed) uimgr.add_ui_from_string(mainMenu) return uimgr.get_widget('/MenuBar') def on_normal_item1(self, widget, event=None, data=None): ''' normal item 1が選択された場合の処理 ''' print 'normal item 1' def on_normal_item2(self, widget, event=None, data=None): ''' normal item 2が選択された場合の処理 ''' print 'normal item 2' def on_toggle_item1(self, action, data=None): ''' toggle item 1が選択された場合の処理 ''' print 'toggle item 1 is %s' % action.get_active() print data def on_toggle_item2(self, action, data=None): ''' toggle item 2が選択された場合の処理 ''' print 'toggle item 2 is %s' % action.get_active() print data def on_radio_menu_changed(self, action, current, data=None): ''' Radioメニューの選択が変更された場合の処理 ''' print 'radio item %d selected' % action.get_current_value() def on_normal_holder_item1(self, widget, event=None, data=None): ''' normal item 1が選択された場合の処理 ''' print 'normal holder item 1' def on_normal_holder_item2(self, widget, event=None, data=None): ''' normal item 2が選択された場合の処理 ''' print 'normal holder item 2' def on_toggle_holder_item1(self, action, data=None): ''' toggle item 1が選択された場合の処理 ''' print 'toggle holder item 1 is %s' % action.get_active() print data def on_toggle_holder_item2(self, action, data=None): ''' toggle item 2が選択された場合の処理 ''' print 'toggle holder item 2 is %s' % action.get_active() print data def on_radio_holder_menu_changed(self, action, current, data=None): ''' Radioメニューの選択が変更された場合の処理 ''' print 'radio holder item %d selected' % action.get_current_value() def on_quit(self, widget, event=None, data=None): print '-- quit --' gtk.main_quit() return False # # def main(): wind = simpleWindow() # # if __name__ == '__main__': main()
メニュー項目にサブメニューを作る場合のポイントは、
・UIManagerに渡すXML文字列中で
タグをを利用する。
・のnameは画面上には表示されない。
・の子供の階層に を記述すると、それがサブメニューとなる。
・サブメニュー用のアクション追加方法は、通常のメニューの場合と全く同じ。
と言った感じです。
思ったよりも簡単でよかったです。
pygtkで遊ぼうシリーズでは、今のところGladeなどのUI作成ツールを全く使っていません。
やっぱり、仕組みを理解するには、ゴリゴリと書くのが一番だと思うので(笑
それに、ゴリゴリと書いたとしても、あまりストレスなく作れてしまうので、小さいアプリを作るぶんにはそのほうが簡単かもしれません。
一通りのウィジェットで遊び終わったら、今度はGladeを使って遊ぼうと思っています。
さて、コピーツールの続きをやろうかな。(笑