I would like to create a "primary menu" programmatically, which I believe is also called a "hamburger menu". I have done several of these while working on web development side, but I have never done these using Python and GTK. This topic seems to be controversial and there are a lot of different solutions out there. I would like to create a menu like this using the non-deprecated way.
In the documentation is mentioned that the old style menus are deprecated (the whole section is archived under "deprecated"): https://python-gtk-3-tutorial.readthedocs.io/en/latest/menus.html
In this example, the whole HeaderBar is made programmatically and a (popover) menu is added into it: GtkMenuButton popups
While that seems to do the trick, it's not a "hamburger" menu and the documentation seems to suggest "Your menus should be defined in XML using Gio.Menu": https://python-gtk-3-tutorial.readthedocs.io/en/latest/application.html#menus
So I am quite lost here. Can someone give me an example how to achieve this? Preferably done programmatically, but if the XML is the only way then so be it.
I post my solution that I was able to do with the kind help from irc.gnome.org #python channel. It's not perfect, menu actions are still not working, but at least I got the menu done which was the point of this post.
#!/usr/bin/env python3
# Python imports
import sys
# GTK imports
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gio
from gi.repository import Gtk
class AppWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_border_width(10)
self.set_default_size(640, 480)
open_selection = Gtk.ModelButton(action_name="open_file", label="Open")
about_selection = Gtk.ModelButton(action_name="about_application", label="About")
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, margin=10, spacing=10)
vbox.add(open_selection)
vbox.add(about_selection)
vbox.show_all()
self.popover = Gtk.Popover()
self.popover.add(vbox)
self.popover.set_position(Gtk.PositionType.BOTTOM)
menu_button = Gtk.MenuButton(popover=self.popover)
menu_icon = Gtk.Image.new_from_icon_name("open-menu-symbolic", Gtk.IconSize.MENU)
menu_icon.show()
menu_button.add(menu_icon)
menu_button.show()
headerbar = Gtk.HeaderBar()
headerbar.props.show_close_button = True
headerbar.props.title = "Hamburger Menu Demo"
headerbar.add(menu_button)
headerbar.show()
self.set_titlebar(headerbar)
def open_file(self, widget):
print("Open file")
class Application(Gtk.Application):
def __init__(self, *args, **kwargs):
super().__init__(*args, application_id="org.example.myapp")
self.window = None
def do_startup(self):
Gtk.Application.do_startup(self)
action = Gio.SimpleAction.new("open_file", None)
action.connect("activate", self.open_file)
action.set_enabled(True)
self.add_action(action)
action = Gio.SimpleAction.new("about_application", None)
action.connect("activate", self.on_about)
self.add_action(action)
action = Gio.SimpleAction.new("quit", None)
action.connect("activate", self.on_quit)
self.add_action(action)
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 open_file(self, action, param):
print("Open file")
def on_about(self, action, param):
print("About application")
def on_quit(self, action, param):
self.quit()
if __name__ == "__main__":
app = Application()
app.run(sys.argv)