How do I make a Gtk4 application with a menu bar in Vala?

114 views Asked by At

I attempted to make a simple Gtk4 application, and I tried to add a menu bar with a menu that does two things: print “Hello, World” and quit.

The code compiles as expected with the command

valac --pkg=gtk4 menutest.vala

However, although the window appears, the menu bar does not. I have tried this in both macOS (using Homebrew) and Fedora. What am I doing wrong?

Here is the sample code:

// menutest.vala

using Gtk;

public class Menutest : Gtk.Application {

    public Menutest() {
        Object (application_id: "org.gtk.menutest");
    }

    protected override void activate() {
        var window = new ApplicationWindow (this);
        window.title = "Hello World";
     
        // Create a menu with two items
        var menu = new Menu();
        menu.insert(0, "Hello", "app.hello");
        menu.insert(1, "Quit", "app.quit");

        // Set the menu as the application's menubar
        this.set_menubar(menu);

        // Define the actions for the menu items
        SimpleAction hello = new SimpleAction("hello", null);
        hello.activate.connect(hello_action);
        this.add_action(hello);

        SimpleAction quit = new SimpleAction("quit", null);
        quit.activate.connect(quit_action);
        this.add_action(quit);

        window.present();
    }

    public static int main (string[] args) {
        return new Menutest().run (args);
    }

    // The callback function for the "Hello" action
    private void hello_action (SimpleAction action, Variant? parameter) {
        print ("Hello, world!\n");
    }

    // The callback function for the "Quit" action
    private void quit_action (SimpleAction action, Variant? parameter) {
        this.quit ();
    }
}

The result in macOS (no menus are added at the top of the screen either):

enter image description here

The result in Fedora:

enter image description here

1

There are 1 answers

1
Colin Kiama On BEST ANSWER

The issue was that you were missing a submenu item for the menu bar. After adding the submenu, the code now works as expected:

using Gtk;

public class Menutest : Gtk.Application {

    public Menutest() {
        Object (application_id: "org.gtk.menutest");
    }

    protected override void activate() {
        var window = new ApplicationWindow (this);
        window.title = "Hello World";
     
        // Create root menu (menu bar).
        var menu = new Menu ();
        
        // Create window submenu and insert (The "Window" entry you'll see in the menu bar)
        var window_menu = new Menu ();
        window_menu.insert(0, "Hello", "app.hello");
        window_menu.insert(1, "Quit", "app.quit");

        // Add window submenu to menu bar
        menu.append_submenu ("Window", window_menu);
        
        // Set the menu as the application's menubar
        this.set_menubar(menu);
        window.set_show_menubar (true);

        // Define the actions for the menu items
        SimpleAction hello = new SimpleAction("hello", null);
        hello.activate.connect(hello_action);
        this.add_action(hello);

        SimpleAction quit = new SimpleAction("quit", null);
        quit.activate.connect(quit_action);
        this.add_action(quit);

        window.present();
    }

    public static int main (string[] args) {
        return new Menutest().run (args);
    }

    // The callback function for the "Hello" action
    private void hello_action (SimpleAction action, Variant? parameter) {
        print ("Hello, world!\n");
    }

    // The callback function for the "Quit" action
    private void quit_action (SimpleAction action, Variant? parameter) {
        this.quit ();
    }
}

GTK4 Hello World App with menu bar containing one submenu item labelled "Window"