[Python,Gtk4] Gtk.PopoverMenuBarの使用について① Gio.MenuやGio.MenuItemを使用したメニューバーの作成

Gtk.PopoverMenuBarの使用

 Gtk4で下図のようなメニューバーは、Gtk.PopoverMenuBarを使用して作成します。メニューの項目を自分で記述する場合はGio.MenuとGio.MenuItemで作成して、それをGtk.PopoverMenuBarにmodelとして追加します。

 また、項目を選択した場合の処理は、Gtk.ApplicationやGtk.ApplicationWindowに追加したGio.SimpleActionに記入して、それをGtk.MenuItemと紐付けることで指定します。

 今回は、Gtk.PopoverMenuBarの作成方法と、メニューの項目をクリックした場合の処理の記入について紹介します。

今回紹介する内容
 ・ Gtk.PopoverMenuBarを作成する
 ・ アクション(Gio.SimpleAction)を設定する

Gtk.PopoverMenuBarの作成

Gtk.PopoverMenuBarを作成する

Gtk.ApplicationWindowを使用する

 メニューバーのアクションの指示に使用するGio.SimpleActionの内、Windowに載せたWidgetの操作に関係するアクションはWindowに追加する必要が有ります。しかし、Gtk.WindowはGio.ActionMapを継承していないため、アクションの追加が行えません。このため、Gtk.Windowの代わりにGio.ActionMapを継承しているGtk.ApplicationWidnowを使用します。

 Window内のWidgetを操作するアクションはGtk.ApplicationWindow内で、そうでないものはGtk.Application内で定義(Gio.SimpleActionの作成)します。

メニューを(model)を作成する

 下図のようなメニューバーを作成する場合、大元となるものと’ファイル’や’ヘルプ’はGio.Menuで定義し、’ラベル変更’,’終了’,’バージョン情報’のような選択項目はGio.MenuItemで定義します。これから、それぞれの定義方法と追加の方法を上から順番に見ていきます。

上図のmodelを作成する場合の構成

Gio.Menu : name=menu   # 大元になるもの
  -  Gio.Menu : name=menu_file  label=’ファイル’
       - Gio.MenuItem : name=file_labeltc  label='ラベル変更' 
        - Gio.MenuItem : name=file_quit     label='終了'
 
  -  Gio.Menu : name=menu_about label='ヘルプ'
        - Gio.MenuItem : name=help_about    label='バージョン情報'

メニューの大元のmenuはGio.Menu.new()により定義します。

        # メニューの大元
        menu = Gio.Menu.new()

 ’ファイル’や’ヘルプ’も、Gio.Menu.new()により定義して、メソッドappend_submenu()により、menu(メニューの大元)に追加します。

        # メニュー'ファイル'
        menu_file = Gio.Menu.new()

        # メニュー'ファイル'をラベルを付けてメニューの大元に追加
        menu.append_submenu('ファイル', menu_file)

 ’ラベル変更’、’終了’、’バージョン情報’は、Gio.MenuItem.new()により定義します。その引数はlabelとdetailed_actionであり、detailed_actionには、「appもしくはwin + ‘.’ + アクション名」を記入します。

 app : Gtk.Applicationに追加されたアクションを指定
 win:Gtk.ApplicationWindowに追加されたアクションを指定

 定義したGio.MenuItemは、Gio.Menuのメソッドappend_item()により、’ファイル’や’ヘルプ’に追加します。

        # 'ファイル'の項目作成: ラベル変更、終了
        file_labeltc = Gio.MenuItem.new(
            label='ラベル変更', detailed_action='win.label_tc')
        file_quit = Gio.MenuItem.new(label='終了', detailed_action='app.quit')

        # メニュー'ファイル'に項目追加: ラベル変更、終了
        menu_file.append_item(file_labeltc)
        menu_file.append_item(file_quit)

Gtk.PopoverMenuBarへのmodelを追加する

 Gtk.PopoverMenuBarへのmodelの追加は、定義時に指定する場合はメソッドnew_from_model()、後から設定する場合はset_menu_model()で行います。

        # Gtk.PopoverMenuBarにメニューを設定
        menubar = Gtk.PopoverMenuBar.new_from_model(menu)

アクション(Gio.SimpleAction)を設定する

 アクションを設定は、Gio.SimpleAction.newでおこないます。その引数は、アクション名とパラメーターのタイプ(パラメーターがない場合は None)の2つです。
 定義したアクションに対してメソッドconnectによりシグナル’activate’と関数とを紐付けて、それをGtk.ApplicationもしくはGtk.ApplicationWindowにメソッドadd_action()で追加します。

# Gtk.ApplicationWindow
        # 'ラベル変更'用のアクション
        action = Gio.SimpleAction.new("label_tc", None)
        action.connect("activate", self.on_label_change)
        self.add_action(action)
# Gtk.Application
    def do_startup(self):
        Gtk.Application.do_startup(self)

        # '終了'用のアクション
        action = Gio.SimpleAction.new('quit', None)
        action.connect('activate', self.on_quit)
        self.add_action(action)

        # 'バージョン情報'用のアクション
        action = Gio.SimpleAction.new("about", None)
        action.connect("activate", self.on_about)
        self.add_action(action)

アクションで呼び出される関数

 アクションで呼び出される関数は、以下のように3つの値(以下の書き方では、self, action, param)を受け取ります。

    # アクションlabel_tcの処理
    def on_label_change(self, action, param):
        self.label.set_text('Good-Bye')

サンプルプログラム

 以下のサンプルプログラムを実行すると、下図のような画面が表示されます。メニューバーの’ラベル変更’を押すと、’hello’が’Good-Bye’に変わります。
 また、’バージョン情報’を押すとGtk.AboutDialogが表示され、’終了’を押すとプログラムが終了します。

Gtk.PopoverMenuBarを使用したメニュー画像
Gtk.PopoverMenuBarを使用したメニュー画像: 項目

Gtk.AboutDialogに使用するアイコン画像(下のSmple Iconと表示した画像)
サンプルプログラムと同じフォルダに保存してから実行してください

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio


APPID = 'com.github.taniyoshima.g4_fblog_menubar'


class Gtk4TestTest(Gtk.ApplicationWindow):

    def __init__(self, app):
        Gtk.Window.__init__(
            self, application=app, title='Gtk.PopoverMenuBar Test',
            height_request=150, width_request=350
        )

        # 'ラベル変更'用のアクション
        action = Gio.SimpleAction.new("label_tc", None)
        action.connect("activate", self.on_label_change)
        self.add_action(action)

        # メニューの大元
        menu = Gio.Menu.new()

        # メニュー'ファイル'
        menu_file = Gio.Menu.new()

        # 'ファイル'の項目作成: ラベル変更、終了
        file_labeltc = Gio.MenuItem.new(
            label='ラベル変更', detailed_action='win.label_tc')
        file_quit = Gio.MenuItem.new(label='終了', detailed_action='app.quit')

        # メニュー'ヘルプ'
        menu_about = Gio.Menu.new()

        # 'ヘルプ'の項目作成: バージョン情報
        help_about = Gio.MenuItem.new(
            label='バージョン情報', detailed_action='app.about')

        # メニュー'ファイル'に項目追加: ラベル変更、終了
        menu_file.append_item(file_labeltc)
        menu_file.append_item(file_quit)

        # メニュー'ファイル'をラベルを付けてメニューの大元に追加
        menu.append_submenu('ファイル', menu_file)

        # メニュー'ヘルプ'に項目追加: バージョン情報
        menu_about.append_item(help_about)

        # メニュー'ヘルプ'をラベルを付けてメニューの大元に追加
        menu.append_submenu('ヘルプ', menu_about)

        # Gtk.PopoverMenuBarにメニューを設定
        menubar = Gtk.PopoverMenuBar.new_from_model(menu)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.append(menubar)
        self.label = Gtk.Label(label='hello')
        vbox.append(self.label)
        self.set_child(vbox)

    # アクションlabel_tcの処理
    def on_label_change(self, action, param):
        self.label.set_text('Good-Bye')


class Gtk4TestApp(Gtk.Application):

    def __init__(self):
        Gtk.Application.__init__(self, application_id=APPID)

    def do_startup(self):
        Gtk.Application.do_startup(self)

        # '終了'用のアクション
        action = Gio.SimpleAction.new('quit', None)
        action.connect('activate', self.on_quit)
        self.add_action(action)

        # 'バージョン情報'用のアクション
        action = Gio.SimpleAction.new("about", None)
        action.connect("activate", self.on_about)
        self.add_action(action)

    def do_activate(self):
        win = Gtk4TestTest(self)
        win.present()

    # アクションquitの処理
    def on_quit(self, action, param):
        self.quit()

    # アクションaboutの処理
    def on_about(self, action, param):
        icon = Gtk.Picture.new_for_filename('icon.png').get_paintable()
        dialog = Gtk.AboutDialog(
            authors=['taniyoshima'],
            comments='AboutDialogのサンプル',
            license_type=Gtk.License.MIT_X11,
            version='1.0.0',
            program_name='Gtk.AboutDialog Test',
            logo=icon
        )

        dialog.present()


def main():
    app = Gtk4TestApp()
    app.run()


if __name__ == '__main__':
    main()
タイトルとURLをコピーしました