[Gtk.Template]Gtk.HeaderBarの使用

目標

 Gtk.HeaderBarは、Windows のカスタム タイトル バーを作成するためのウィジェットです。Gtk.HeaderBarもXMLデータで作成することが可能であり、それに追加するボタンやメニューもXMLデータで作成することができます。

 今回は、XMLデータでGtk.HeaderBarをウィンドウに設置する方法や、Gtk.HeaderBarへの載せたボタンの追加、追加したものの動作の指定方法を紹介します。

今回紹介する内容
 ・ XMLデータでGtk.HeaderBarを作成する
 ・ XMLデータでGtk.HeaderBarにボタンを追加する
 ・ XMLデータでGtk.HeaderBarにメニューを追加する
 ・ Gtk.HeaderBarに載せたボタンなどの動作(action関係)を設定する

Gtk.HeaderBarの定義

XMLデータでGtk.HeaderBarを作成する

 Gtk.HeaderBarのXMLデータによる定義は、以下のように記入します。
 1. <child type=’titlebar’></child>内に記入する。
 2. <object class=”GtkHeaderBar”></object>により、Gtk.HeaderBarを定義する。
 3. 2.の中に<property>や<child>などの情報を記入する。

<child type="titlebar">
  <object class="GtkHeaderBar">
  …省略…
  </object>
</child>

XMLデータでGtk.HeaderBarにボタンを追加する

 Gtk.HeaderBarへのボタン(Child:Gtk.Widget)の追加は、以下のように<child type=”start”>もしくは<child type=”end”>によりおこないます。

 <child type=”start”>を指定するとChildはGtk.HeaderBarの左側に表示され、<child type=”end”>にするとChildはGtk.HeaderBarの右側に表示されます。

    <child type="start">
      <object class="GtkButton">
        <property name="icon-name">pan-start-symbolic</property>
        <property name="action-name">win.on_button_clicked</property>
      </object>
    </child>
    <child type="end">
      <object class="GtkMenuButton">
        <property name="icon-name">open-menu-symbolic</property>
        <property name="popover">popover</property>
      </object>
    </child>

XMLデータでGtk.HeaderBarにメニューを追加する

 下図のような、Gtk.HeaderBarにPopoverによりメニューを作るには、ボタン(Gtk.MenuButton)とPopoverを定義します。

Gtk.MenuButtonの作成

 Gtk.MenuButtonは、以下のように記入することでicon-nameが’open-menu-symbolic’、popoverがpopover(下のGtk.Popoverのid名)と指定します。

    </child>
    <child type="end">
      <object class="GtkMenuButton">
        <property name="icon-name">open-menu-symbolic</property>
        <property name="popover">popover</property>
      </object>
    </child>

Gtk.Popoverの作成

 Gtk.Popoverは、以下のように<object class=”GtkPopover” id=”id名”></object>内にGtk.BoxやGtk.Buttonでchildを記入して、作成します。

  <object class="GtkPopover" id="popover">
    <child>
      <object class="GtkBox" id="pop_box">
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkButton" id="item1_button">
            <property name="action-name">win.on_item1_clicked</property>
            <property name="label">アイテム1</property>
          </object>
        </child>
        <child>
          <object class="GtkButton" id="item2_button">
            <property name="action-name">win.on_item2_clicked</property>
            <property name="label">アイテム2</property>
          </object>
        </child>
      </object>
    </child>
  </object>

Gtk.MenuButtonを押してGtk.Popoverを表示する時に、エラー’_gtk_css_corner_value_get_x: assertion ‘corner->class == &GTK_CSS_VALUE_CORNER’ failed’が出ますが、これはGtk4の修正待ちのようです。

Menu button gives error messages with latest GTK4

Gtk.HeaderBarに載せたボタンなどの動作(action関係)を設定する

 Gtk.HeaderBarに載せたボタンやPopoverを押した場合の処理の追加は、以下のようにPyhonファイルに記入します。

 ※ アクション関係の記述方法は、Gtk.PopoverMenuBarについてを確認してください。

    action = Gio.SimpleAction.new("on_button_clicked", None)
    action.connect("activate", self.on_button_clicked)
    self.add_action(action)
    def on_button_clicked(self, action, param):
        print('ボタンが押されました。')

サンプルプログラム

 以下のサンプルプログラムを実行すると図のようなGtk.HeaderBar付きのWindowが表示されます。左端の矢印ボタンを押すとターミナルにメッセージが表示され、右のボタン(open-menu-symbolic)を押すとGtk.Popoverが表示されます。Gtk.Popoverの項目を押しても、ターミナルにメッセージが表示されます。

実行方法

 下の2つのファイルを同じフォルダに保存して、そのフォルダで以下のコマンドを実行します。

python main.py
<?xml version='1.0' encoding='UTF-8'?>
<interface>
  <template class="window" parent="GtkApplicationWindow">
    <property name="default_width">500</property>
    <property name="default_height">200</property>
    <property name="title">Template HeaderBar Test</property>
    <child type="titlebar">
      <object class="GtkHeaderBar">
        <child type="start">
          <object class="GtkButton">
            <property name="icon-name">pan-start-symbolic</property>
            <property name="action-name">win.on_button_clicked</property>
          </object>
        </child>
        <child type="end">
          <object class="GtkMenuButton">
            <property name="icon-name">open-menu-symbolic</property>
            <property name="popover">popover</property>
          </object>
        </child>
      </object>
    </child>
  </template>
  <object class="GtkPopover" id="popover">
    <child>
      <object class="GtkBox" id="pop_box">
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkButton" id="item1_button">
            <property name="action-name">win.on_item1_clicked</property>
            <property name="label">アイテム1</property>
          </object>
        </child>
        <child>
          <object class="GtkButton" id="item2_button">
            <property name="action-name">win.on_item2_clicked</property>
            <property name="label">アイテム2</property>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>
import os
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio


APPID = 'com.github.taniyoshima.g4_fblogt_headerbar'


@Gtk.Template(filename=os.path.dirname(__file__) + '/ui_file.ui')
class Gtk4TestTest(Gtk.ApplicationWindow):
    __gtype_name__ = "window"

    popover = Gtk.Template.Child()

    def __init__(self, app):
        Gtk.Window.__init__(
            self, application=app)

        action = Gio.SimpleAction.new("on_button_clicked", None)
        action.connect("activate", self.on_button_clicked)
        self.add_action(action)

        action = Gio.SimpleAction.new("on_item1_clicked", None)
        action.connect("activate", self.on_item1_clicked)
        self.add_action(action)

        action = Gio.SimpleAction.new("on_item2_clicked", None)
        action.connect("activate", self.on_item2_clicked)
        self.add_action(action)

    def on_button_clicked(self, action, param):
        print('ボタンが押されました。')

    def on_item1_clicked(self, action, param):
        print('アイテム1が押されました。')
        self.popover.set_visible(False)

    def on_item2_clicked(self, action, param):
        print('アイテム2が押されました。')
        self.popover.set_visible(False)


class Gtk4TestApp(Gtk.Application):

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

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


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


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