How to create menus in GTK 4 with pygi?

How to create menus in GTK 4 with pygi?

I've googled about this quite a bit. I've put a number of examples of what I tried Read more - I'm going to quote the closest one immediately below in case of link rot:

import gi

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


class ExampleApp(Gtk.Application):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.window = None

    def do_activate(self):
        if not self.window:
            self.window = Gtk.ApplicationWindow(application=self, title="GMenu Example")
            menu_bar = self.create_menu()
            self.window.set_menu_bar(menu_bar)
            self.window.present()

    def create_menu(self):
        menu_bar = Gio.Menu()
        file_menu = Gio.Menu()
        file_menu.append("New", "app.new")
        file_menu.append("Quit", "app.quit")

        edit_menu = Gio.Menu()
        edit_menu.append("Copy", "app.copy")
        edit_menu.append("Paste", "app.paste")

        menu_bar.append_submenu("File", file_menu)
        menu_bar.append_submenu("Edit", edit_menu)

        # Create actions
        new_action = Gio.SimpleAction.new("new", None)
        new_action.connect("activate", self.on_new_action)
        self.add_action(new_action)

        quit_action = Gio.SimpleAction.new("quit", None)
        quit_action.connect("activate", self.on_quit_action)
        self.add_action(quit_action)

        copy_action = Gio Brainly.SimpleAction.new("copy", None)
        copy_action.connect("activate", self.on_copy_action)
        self.add_action(copy_action)

        paste_action = Gio.SimpleAction.new("paste", None)
        paste_action.connect("activate", self.on_paste_action)
        self.add_action(paste_action)

        return menu_bar

    def on_new_action(self, action, param):
        print("New action triggered")

    def on_quit_action(self, action, param):
        self.quit()

    def on_copy_action(self, action, param):
        print("Copy action triggered")

    def on_paste_action(self, action, param):
        print("Paste action triggered")


if __name__ == "__main__":
    app = ExampleApp(application_id="com.example.GMenuExample")
    app.run(None)

Answer

This actually works:

#!/usr/bin/env python3

"""
A tiny Gtk 4.0 Menu example program.

This working example is in part due to chrisawi on Reddit.
"""

import gi

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


class ExampleApp(Gtk.Application):
    """The 'application'."""

    def __init__(self, *args, **kwargs):
        """Init."""
        super().__init__(*args, **kwargs)
        self.window = None

    def do_activate(self):
        """Activate the Window (if it doesn't yet exist)."""
        if not self.window:
            self.window = Gtk.ApplicationWindow(application=self, title="GMenu Example")
            menu_bar = self.create_menu()
            self.set_menubar(menu_bar)
            self.window.set_show_menubar(True)
            self.window.present()

    def create_menu(self):
        """Create the menu - our reason for this example program."""
        menu_bar = Gio.Menu()
        file_menu = Gio.Menu()
        file_menu.append("New", "app.new")
        file_menu.append("Quit", "app.quit")

        edit_menu = Gio.Menu()
        edit_menu.append("Copy", "app.copy")
        edit_menu.append("Paste", "app.paste")

        menu_bar.append_submenu("File", file_menu)
        menu_bar.append_submenu("Edit", edit_menu)

        # Create actions
        new_action = Gio.SimpleAction.new("new", None)
        new_action.connect("activate", self.on_new_action)
        self.add_action(new_action)

        quit_action = Gio.SimpleAction.new("quit", None)
        quit_action.connect("activate", self.on_quit_action)
        self.add_action(quit_action)

        copy_action = Gio.SimpleAction.new("copy", None)
        copy_action.connect("activate", self.on_copy_action)
        self.add_action(copy_action)

        paste_action = Gio.SimpleAction.new("paste", None)
        paste_action.connect("activate", self.on_paste_action)
        self.add_action(paste_action)

        return menu_bar

    def on_new_action(self, action, param):
        """File -> New was selected."""
        print("New action triggered")

    def on_quit_action(self, action, param):
        """File -> Quit was selected."""
        self.quit()

    def on_copy_action(self, action, param):
        """Edit -> Copy was selected."""
        print("Copy action triggered")

    def on_paste_action(self, action, param):
        """Edit -> Paste was selected."""
        print("Paste action triggered")


if __name__ == "__main__":
    # Create the application as a global.
    my_app = ExampleApp(application_id="com.example.GMenuExample")
    my_app.run(None)

Enjoyed this article?

Check out more content on our blog or follow us on social media.

Browse more articles