Paepoi » PyGObject Tips » Gtk(PyGObject) Tips | メニュー
Gtk(PyGObject) Tips | メニュー
# 最終更新日 2019.09.01
2019 年現在の仕様に追記と書き換え。
popover と popup のプロパティがあり GtkPopoverMenu と GtkMenu どちらを使うかを選べます。
GtkPopoverMenu は下で解説するのでここでは従来のメニューを出す方法を。
作成するとデフォルトは矢印表示のボタンになります。
GNOME 標準アプリは全部こちらを採用しており事実上の標準になっています。
コンテナ(3.10 以降)#GtkPopoverMenuでも書いていますが。
ここではサブメニューを表示させるサンプルを。
しかしコンテキストメニュー(右クリックメニュー)はまだバリバリ使われている。
GtkTextView 等は独自のコンテキストメニューがあるのでそれ以外で。
GtkMenuBar, GtkToolbar なので注意、統一される前に無くなると思うけど。
2019 年現在の仕様に追記と書き換え。
GtkMenuButton
GtkMenuButton は Nautilus 3.6 から採用されているボタン式メニュー。popover と popup のプロパティがあり GtkPopoverMenu と GtkMenu どちらを使うかを選べます。
GtkPopoverMenu は下で解説するのでここでは従来のメニューを出す方法を。
作成するとデフォルトは矢印表示のボタンになります。
#!/usr/bin/env python3 import sys, gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gdk class Win(Gtk.ApplicationWindow): ''' こっちを使っている GNOME アプリが存在しないけど ''' def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title='Py') # AccelGroup accelgroup = Gtk.AccelGroup() self.add_accel_group(accelgroup) # MenuIten item_open = Gtk.MenuItem(label='_Open', use_underline=True, visible=True) item_open.connect('activate', self.on_open) item_quit = Gtk.MenuItem(label='_Quit', use_underline=True, visible=True) item_quit.connect('activate', self.on_quit) # Keyboard Shortcut item_open.add_accelerator('activate', accelgroup, Gdk.KEY_o, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) item_quit.add_accelerator('activate', accelgroup, Gdk.KEY_q, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) # Menu menu = Gtk.Menu() menu.append(item_open) menu.append(Gtk.SeparatorMenuItem(visible=True)) menu.append(item_quit) # GtkMenuButton menubutton = Gtk.MenuButton() menubutton.set_popup(menu) # これで矢印の向きを変更できる #menubutton.set_direction(Gtk.ArrowType.UP) # ヘッダーバーに置く hbar = Gtk.HeaderBar(show_close_button=True) hbar.pack_end(menubutton) # GtkTextView self.textview = Gtk.TextView() sw = Gtk.ScrolledWindow(child=self.textview) # self self.set_titlebar(hbar) self.add(sw) self.resize(200, 100) self.show_all() def on_open(self, action): dlg = Gtk.FileChooserNative( title='開く', transient_for=self, action=Gtk.FileChooserAction.OPEN) if dlg.run() == Gtk.ResponseType.ACCEPT: f = dlg.get_filename() with open(f) as o: s = o.read() self.textview.props.buffer.props.text = s dlg.destroy() def on_quit(self, action): self.close() def on_button_press_event(self, widget, event): print(event.button) return False class App(Gtk.Application): def __init__(self): Gtk.Application.__init__(self) def do_startup(self): Gtk.Application.do_startup(self) Win(self) def do_activate(self): self.props.active_window.present() app = App() app.run(sys.argv)
GtkModelButton
GtkPopoverMenu には GtkMenuItem ではなく GtkModelButton を入れます。GNOME 標準アプリは全部こちらを採用しており事実上の標準になっています。
コンテナ(3.10 以降)#GtkPopoverMenuでも書いていますが。
ここではサブメニューを表示させるサンプルを。
#!/usr/bin/env python3 import sys, gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gio class Win(Gtk.ApplicationWindow): ''' サブメニューを使うには menu-name プロパティに子プロパティの submenu に登録した名前をセット 最初に add した widget が自動でメインメニューになり submenu は main になります ニーモニックはデフォルトで ON なので use-underline 指定は不要 ''' def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title='Py') # メインメニュー menu_open = Gtk.ModelButton(action_name='app.new_window_action', text='新しいウインドウ(_N)') menu_new = Gtk.ModelButton(menu_name = 'tool_page', text='ツール(_T)') menu_quit = Gtk.ModelButton(action_name='app.quit_action', text='終了(_Q)') # vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, margin=10) vbox.pack_start(menu_open, False, False, 0) vbox.pack_start(menu_new, False, False, 0) vbox.pack_start(Gtk.Separator(), False, False, 0) vbox.pack_start(menu_quit, False, False, 0) # ツールメニュー menu_back = Gtk.ModelButton(menu_name = 'main', inverted=True, centered=True, text='ツール(_T)') menu_set = Gtk.ModelButton(action_name='win.set_title_action', text='セットタイトル(_S)') menu_append = Gtk.ModelButton(action_name='win.append_title_action', text='追加でタイトル(_A)') # tool_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, margin=10) tool_box.pack_start(menu_back, False, False, 0) tool_box.pack_start(menu_set, False, False, 0) tool_box.pack_start(menu_append, False, False, 0) # GtkPopoverMenu self.popovermenu = Gtk.PopoverMenu() self.popovermenu.add(vbox) self.popovermenu.add(tool_box) self.popovermenu.child_set_property(tool_box, 'submenu', 'tool_page') # MenuButton open_image = Gtk.Image(icon_name='open-menu-symbolic', icon_size=Gtk.IconSize.MENU) self.menu_button = Gtk.MenuButton(image=open_image, popover=self.popovermenu) self.menu_button.connect('toggled', self.on_menu_button_toggled) # GtkHeaderBar hbar = Gtk.HeaderBar(show_close_button=True) hbar.pack_end(self.menu_button) self.set_titlebar(hbar) # GAction f10_action = Gio.SimpleAction(name='f10_action') set_title_action = Gio.SimpleAction(name='set_title_action') append_title_action = Gio.SimpleAction(name='append_title_action') self.add_action(f10_action) self.add_action(set_title_action) self.add_action(append_title_action) f10_action.connect('activate', self.on_f10_action) set_title_action.connect('activate', self.on_set_title_action) append_title_action.connect('activate', self.on_append_title_action) # self self.resize(240, 200) self.show_all() def on_f10_action(self, action, parameter): self.menu_button.clicked() def on_set_title_action(self, action, parameter): self.props.title = 'あ' def on_append_title_action(self, action, parameter): self.props.title += 'い' def on_menu_button_toggled(self, button): if button.props.active: self.popovermenu.show_all() class App(Gtk.Application): def __init__(self): Gtk.Application.__init__(self) def do_startup(self): Gtk.Application.do_startup(self) # GAction new_window_action = Gio.SimpleAction(name='new_window_action') quit_action = Gio.SimpleAction(name='quit_action') # Add self.add_action(new_window_action) self.add_action(quit_action) # Keyboard Shortecut (app) self.set_accels_for_action('app.new_window_action', ['<Control>N']) self.set_accels_for_action('app.quit_action', ['<Control>Q']) # Keyboard Shortecut (win) self.set_accels_for_action('win.f10_action', ['F10']) self.set_accels_for_action('win.set_title_action', ['<Control>S']) self.set_accels_for_action('win.append_title_action', ['<Control>A']) # Signal new_window_action.connect('activate', self.on_new_window_action) quit_action.connect('activate', self.on_quit_action) # Window Win(self) def on_new_window_action(self, action, parameter): Win(self) def on_quit_action(self, action, parameter): self.quit() def do_activate(self): self.props.active_window.present() app = App() app.run(sys.argv)
コンテキストメニュー
GNOME 標準アプリからはメニューバー、ツールバーは無くなりました。しかしコンテキストメニュー(右クリックメニュー)はまだバリバリ使われている。
GtkTextView 等は独自のコンテキストメニューがあるのでそれ以外で。
#!/usr/bin/env python3 import sys, os, gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gdk class Win(Gtk.ApplicationWindow): ''' ウインドウのどこかでマウス右ボタンを押してね ''' def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title='Py') # MenuIten item_open = Gtk.MenuItem(label='_Open', use_underline=True, visible=True) item_open.connect('activate', self.on_open) item_quit = Gtk.MenuItem(label='_Quit', use_underline=True, visible=True) item_quit.connect('activate', self.on_quit) # アクセラレーターの登録は GAction 等でおこなっているならしない accelgroup = Gtk.AccelGroup() self.add_accel_group(accelgroup) item_open.add_accelerator('activate', accelgroup, Gdk.KEY_o, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) item_quit.add_accelerator('activate', accelgroup, Gdk.KEY_q, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) # この Menu をドロップする self.menu = Gtk.Menu() self.menu.append(item_open) self.menu.append(Gtk.SeparatorMenuItem(visible=True)) self.menu.append(item_quit) # label self.label = Gtk.Label(label='filename') self.add(self.label) # self self.resize(200, 100) self.show_all() def on_open(self, action): dlg = Gtk.FileChooserNative( title='開く', transient_for=self, action=Gtk.FileChooserAction.OPEN) if dlg.run() == Gtk.ResponseType.ACCEPT: f = dlg.get_filename() self.label.set_text(os.path.basename(f)) dlg.destroy() def on_quit(self, action): self.close() def do_button_press_event(self, event): ''' マウス左ボタンは 1、右ボタンは 3 中(ホイール)ボタンは 2 だけど非推奨 ''' if event.button == 3: # self.menu.popup() は 3.22 より非推奨 self.menu.popup_at_pointer() return False class App(Gtk.Application): def __init__(self): Gtk.Application.__init__(self) def do_startup(self): Gtk.Application.do_startup(self) Win(self) def do_activate(self): self.props.active_window.present() app = App() app.run(sys.argv)
GtkMenuBar, GtkToolbar
今や Evolution でしか使われていないメニューバーとツールバーです。GtkMenuBar, GtkToolbar なので注意、統一される前に無くなると思うけど。
#!/usr/bin/env python3 import sys, gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gdk class Win(Gtk.ApplicationWindow): ''' 一応まだ使えるけど... ''' def __init__(self, app): Gtk.ApplicationWindow.__init__(self, application=app, title='Py') # MenuIten item_open = Gtk.MenuItem(label='_Open', use_underline=True) item_open.connect('activate', self.on_open) item_quit = Gtk.MenuItem(label='_Quit', use_underline=True) item_quit.connect('activate', self.on_quit) # Add Accelerator accelgroup = Gtk.AccelGroup() self.add_accel_group(accelgroup) item_open.add_accelerator('activate', accelgroup, Gdk.KEY_o, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) item_quit.add_accelerator('activate', accelgroup, Gdk.KEY_q, Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE) # Menu file_sub_menu = Gtk.Menu() file_sub_menu.append(item_open) file_sub_menu.append(Gtk.SeparatorMenuItem()) file_sub_menu.append(item_quit) # Top MenuItem file_root_menu = Gtk.MenuItem(label='_File', use_underline=True) file_root_menu.set_submenu(file_sub_menu) # MenuBar menubar = Gtk.MenuBar() menubar.append(file_root_menu) # # Toolbar、ストックは非推奨になりました tool_open = Gtk.ToolButton(icon_name='folder-documents-symbolic') tool_open.set_tooltip_text('開く') tool_open.connect('clicked', self.on_open) tool_quit = Gtk.ToolButton(icon_name='window-close-symbolic') tool_quit.set_tooltip_text('終了') tool_quit.connect('clicked', self.on_quit) toolbar = Gtk.Toolbar() toolbar.insert(tool_open, 0) toolbar.insert(Gtk.SeparatorToolItem(), 1) toolbar.insert(tool_quit, 2) # # パッキング drawingarea = Gtk.DrawingArea() vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) vbox.pack_start(menubar, False, True, 0) vbox.pack_start(toolbar, False, True, 0) vbox.pack_start(drawingarea, True, True, 0) self.add(vbox) # いつもの処理 self.resize(200, 200) self.show_all() def on_open(self, widget): pass def on_quit(self, widget): self.close() class App(Gtk.Application): def __init__(self): Gtk.Application.__init__(self) def do_startup(self): Gtk.Application.do_startup(self) Win(self) def do_activate(self): self.props.active_window.present() app = App() app.run(sys.argv)
Copyright(C) sasakima-nao All rights reserved 2002 --- 2024.