Building a basic menu in Gtk4

Hello

I want to make a basic menu in Gtk-rs 4, add it to a vertical box and add it to the window.

But suddenly 'let menu = gtk::Menu::new();` yields

error[E0433]: failed to resolve: could not find `MenuBar` in `gtk`
  --> src/ui.rs:73:21
   |
73 |     let menu = gtk::MenuBar::new();
   |                     ^^^^^^^ could not find `MenuBar` in `gtk`

For some reason I have to use gio. This removes the error:

    let menu = gio::Menu::new();

But when I try to add it to a gtk::Box like this:

    let gtk_box = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .build();
    gtk_box.append(&menu);

It gives the error:

error[E0277]: the trait bound `gio::Menu: IsA<gtk4::Widget>` is not satisfied
   --> src/ui.rs:84:20
    |
84  |     gtk_box.append(&menu);
    |             ------ ^^^^^ the trait `IsA<gtk4::Widget>` is not implemented for `gio::Menu`
    |             |
    |             required by a bound introduced by this call
    |
    = help: the following other types implement trait `IsA<T>`:
              <gio::Menu as IsA<gtk4::glib::Object>>
              <gio::Menu as IsA<gio::Menu>>
              <gio::Menu as IsA<MenuModel>>
note: required by a bound in `gtk4::prelude::BoxExt::append`

Using app.set_menubar(Some(&menu)) instead of a gtk::Box compiles but does not do anything.

How to fix this?

this is very strange, do you have a different gtk (mod, type, alias, etc) in scope by accident?

Which versions are you using? It's also possible that you need to enable a feature flag on gtk, though I'm not familiar with the library to know whether this is the case.

Are you perhaps looking at the documentation for the gtk crate (which does contain a Menu/MenuBar type) while using the gtk4 crate (which is the one reported in your error message)?

Edit: by the way looks like MenuBar was removed in gtk4. You could take a look at PopoverMenuBar, MenuButton or HeaderBar.

I think it got removed from Gtk4.

I tried the following:

    let menu = gtk::PopoverMenu::builder().build();
    let menu_settings = gtk::Label::new(Some("Instellingen"));
    let menu_help = gtk::Label::new(Some("Help"));
    let menu_quit = gtk::Label::new(Some("Sluiten"));
    menu.add_child(&menu_settings, "1");
    menu.add_child(&menu_help, "2");
    menu.add_child(&menu_quit, "3");


    let gtk_box = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .build();
    gtk_box.append(&menu);
    
    let dashboard_window = gtk::ApplicationWindow::builder()
        .application(app)
        .default_width(900)
        .default_height(700)
        .title("Dashboard")
        .child(&gtk_box)
        .build();


    dashboard_window.present();

It compiles but the menu is not shown.

This works.

    let gtk_box = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .build();
    
    let menu_button = gtk::Button::builder()
        .label("Menu")
        .build();
    
    let popover = gtk::Popover::new();
    popover.set_parent(&menu_button);
    

    let item1 = gtk::Button::with_label("item 1");
    let item2 = gtk::Button::with_label("item 2");
    let item3 = gtk::Button::with_label("item 3");

    item1.connect_clicked(move | _button| {
        println!("1 clicked");
    });
    item2.connect_clicked(move | _button| {
        println!("2 clicked");
    });
    item3.connect_clicked(move | _button| {
        println!("3 clicked");
    });
    
    let menu_items = gtk::Box::new(gtk::Orientation::Vertical, 0);
    menu_items.append(&item1);
    menu_items.append(&item2);
    menu_items.append(&item3);
    popover.set_child(Some(&menu_items));
    
    menu_button.connect_clicked(move | _button| {
        popover.popup();
    });
    gtk_box.append(&menu_button);
    

    let dashboard_main_window = gtk::ApplicationWindow::builder()
        .application(app)
        .default_width(400)
        .default_height(500)
        .child(&gtk_box)
        .title("Dashboard")
        .build();
    dashboard_main_window.present();

Open for better suggestions though.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.