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 --- 2025.