Migrating MenuButton to gtkmm4

Hi, I have a MenuButton with an image and a popover in gtkmm3.
I am migrating my app to gtkmm4 and I can’t call set_image() anymore because MenuButton does not derive from ToggleButton like it was in gtkmm3. Now it derived from Widget.
gtkmm: Gtk::MenuButton Class Reference says “The Gtk::MenuButton widget can show either an icon or a label .” but I need a button with an image (not from the icon gallery).
I tried a couple of things:

  1. I tried calling set_parent() to make the image a child of the menubutton but the image is not shown.
  2. I tried using ToggleButton instead of MenuButton but it take 2 clicks to show the popover. This is the toggle method:
    void on_button_toggled()
    {
    bool up = button.get_active();
    popover.set_visible(!up);
    }

How can I create a button with an image an a popover in gtkmm4?

You should be able to augment the icon theme with your custom image using the gtk_icon_theme_add_*_path functions. You can then just use it like any other icon if named and placed correctly (see e.g. GtkIconTheme: GTK 4 Reference Manual)

THX! Is there an example of such action you can point ne to?
I was hoping for a simpler answer though, since MenuButton derives from Gtk::Widget, is there a simple way to place an image on a widget?

I am not a gtkmm fan, and it could be possible that I do not understand your question as well.
If you are asking about how to put an image inside the popover which is related to that button, then this is what I’ll do in C :

#include <gtk/gtk.h>
#include <stdlib.h>

static void activate ( GtkApplication *app )
{
    g_return_if_fail ( GTK_IS_APPLICATION ( app ) );

    GtkWidget *window;
    GtkWidget *menu_button;

    GtkWidget *image;
    GtkWidget *popover;

    /// *** Create the Window
    window = gtk_application_window_new ( app );
    gtk_window_set_default_size ( GTK_WINDOW ( window ), 150, 100 );

    /// *** Create a MenuButton
    menu_button = gtk_menu_button_new ( );
    gtk_menu_button_set_icon_name ( GTK_MENU_BUTTON( menu_button ), "computer" );

    /// *** Create the Popover
    popover = gtk_popover_new ();

    /// *** Create the image
    image = gtk_image_new_from_file ( "icon.png" );
    gtk_widget_set_size_request ( image, 50, 50 );

    /// *** Set the Popover
    gtk_menu_button_set_popover ( GTK_MENU_BUTTON ( menu_button ), popover );

    /// ****Set the child on that Popover
    gtk_popover_set_child ( GTK_POPOVER ( popover ), image );

    /// *** Set the MenuButton
    gtk_window_set_child ( GTK_WINDOW ( window ), menu_button );

    /// *** Show the windowo the screen
    gtk_window_present ( GTK_WINDOW ( window ) );
}

int main ( int argc, char *argv[] )
{
    GtkApplication *app;
    int status;

    /// ***
    app = gtk_application_new ( "this.is.my.id", G_APPLICATION_FLAGS_NONE );

    /// ***
    g_signal_connect_swapped ( app, "activate", G_CALLBACK ( activate ), app );

    /// ***
    status = g_application_run ( G_APPLICATION ( app ), argc, argv );

    return status;
}

Output:
GtkMenuButton-icon

.
.
.
Later Edit:

if you need to put an image on that MenuButton also, then try something like this:

#include <gtk/gtk.h>
#include <stdlib.h>

static void activate ( GtkApplication *app )
{
    g_return_if_fail ( GTK_IS_APPLICATION ( app ) );

    GtkWidget *window;
    GtkWidget *menu_button;

    GtkWidget *image_1;
    GtkWidget *image_2;
    GtkWidget *popover;

    GtkWidget *child;

    /// *** Create the Window
    window = gtk_application_window_new ( app );
    gtk_window_set_default_size ( GTK_WINDOW ( window ), 150, 100 );

    /// *** Create a MenuButton
    menu_button = gtk_menu_button_new ( );

    /// *** Get the first child of the MenuButton
    /* By the way, the first child Is GtkToogleButton */
    child = gtk_widget_get_first_child ( menu_button );

    /// *** Create the Popover
    popover = gtk_popover_new ();

    /// *** Create an image for the Menu Button
    image_1 = gtk_image_new_from_file ( "icon1.png" );
    gtk_widget_set_size_request ( image_1, 50, 50 );

    /// *** Create an image for the Popover
    image_2 = gtk_image_new_from_file ( "icon2.png" );
    gtk_widget_set_size_request ( image_2, 50, 50 );

    /// ****Set the Image_1 on the MenuButton Child
    gtk_button_set_child ( GTK_BUTTON ( child ), image_1 );

    /// ****Set the Image_2 on that Popover
    gtk_popover_set_child ( GTK_POPOVER ( popover ), image_2 );

    /// *** Set the Popover
    gtk_menu_button_set_popover ( GTK_MENU_BUTTON ( menu_button ), popover );

    /// *** Put the MenuButton inside the Window
    gtk_window_set_child ( GTK_WINDOW ( window ), menu_button );

    /// *** Show the window to the screen
    gtk_window_present ( GTK_WINDOW ( window ) );
}

int main ( int argc, char *argv[] )
{
    GtkApplication *app;
    int status;

    /// ***
    app = gtk_application_new ( "this.is.my.id", G_APPLICATION_FLAGS_NONE );

    /// ***
    g_signal_connect_swapped ( app, "activate", G_CALLBACK ( activate ), app );

    /// ***
    status = g_application_run ( G_APPLICATION ( app ), argc, argv );

    return status;
}

Output:
GtkMenuButton-PopOver-Image

That’s great, you solved my problem simple and to the point, THX!!!

1 Like

You’re welcome.
If you need more about GTK check my YouTube channel

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.