[Python] Linking GMenuModel to actions for context menus in Python Gtk3

Discussão em 'Python' iniciado por Stack, Dezembro 17, 2024.

  1. Stack

    Stack Membro Participativo

    I've built an application using Gtk3 and Gtk.Builder, using GMenuModel for the menus. So far so good. Now I'd like to add context (i.e. right-click) menus.

    The menus themselves appear, but as I can't seem to find the right incantation to link the actions, they are always ghosted. Here is my toy code example:

    import sys
    import os
    import gi

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

    _curr_dir = os.path.split(__file__)[0]

    # This would typically be its own file
    MENU_XML = """
    <?xml version="1.0" encoding="UTF-8"?>
    <interface>
    <menu id="context_menu">
    <section>
    <item>
    <attribute name="label" translatable="yes">Option 1</attribute>
    <attribute name="action">app.option1</attribute>
    </item>
    <item>
    <attribute name="label" translatable="yes">Option 2</attribute>
    <attribute name="action">app.option2</attribute>
    </item>
    </section>
    </menu>
    </interface>
    """


    class AppWindow(Gtk.ApplicationWindow):
    def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)

    self.set_default_size(400, 300)
    self.connect("destroy", Gtk.main_quit)

    # Load the UI from the Glade file
    builder = Gtk.Builder()
    builder = Gtk.Builder.new_from_string(MENU_XML, -1)

    # Get the context menu defined in the XML
    self.context_menu = Gtk.Menu.new_from_model(builder.get_object("context_menu"))

    # Add a simple label
    self.label = Gtk.Label(label="Right-click to open context menu")
    self.add(self.label)
    self.label.show()
    # Connect the button press event (right-click)
    self.connect("button-press-event", self.on_right_click)

    def on_right_click(self, widget, event):
    # Check if it's the right-click (button 3)
    if event.button == 3:
    # Show the context menu
    # self.context_menu.popup(None, None, None, None, event.button, event.time)
    self.context_menu.show_all()
    self.context_menu.popup_at_pointer(event)


    class Application(Gtk.Application):

    def __init__(self, *args, **kwargs):
    super().__init__(
    *args,
    application_id="org.example.myapp",
    **kwargs
    )
    self.window = None

    def do_startup(self):
    Gtk.Application.do_startup(self)
    action = Gio.SimpleAction.new("option1", None)
    action.connect("activate", self.on_option1_activated)
    self.add_action(action)
    action = Gio.SimpleAction.new("option2", None)
    action.connect("activate", self.on_option2_activated)
    self.add_action(action)
    builder = Gtk.Builder.new_from_string(MENU_XML, -1)
    self.set_app_menu(builder.get_object("app-menu"))

    def do_activate(self):

    # We only allow a single window and raise any existing ones
    if not self.window:

    # Windows are associated with the application
    # when the last one is closed the application shuts down
    self.window = AppWindow(application=self, title="Main Window")

    self.window.present()

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

    def on_option1_activated(self, widget):
    print("Option 1 selected")

    def on_option2_activated(self, widget):
    print("Option 2 selected")


    if __name__ == "__main__":
    app = Application()
    app.run()


    How can I link up the actions so that I can use the menu?

    Continue reading...

Compartilhe esta Página