在一个小例子中,我不明白这是什么问题。
我想用Gmenu而不在GtkApplication中实现Gaction

首先请用GtkApplication找到一个小例子

我拿了here

#include <gtk/gtk.h>
//menubuttonexample.c
/*  Compile with:
 *  gcc -std=c11 -Wall -fmax-errors=10 -Wextra menubuttonexample.c -o menubuttonexample `pkg-config --cflags --libs gtk+-3.0 `
 */

/* Callback function for the undo action */
static void about_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    g_print ("You clicked \"About\"\n");
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}
static void new_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    g_print ("You clicked \"New\"\n");
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}

static void quit_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    GApplication *application = user_data;
    g_application_quit (application);
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}

static void activate (GtkApplication *app,  gpointer user_data)
{
    GMenu *submenu;
    GtkWidget *grid;
    GMenu *menumodel;
    GtkWidget *window;
    GtkWidget *menubutton;
    GSimpleAction *about_action;

    window = gtk_application_window_new (app);
    grid = gtk_grid_new ();

    gtk_window_set_title (GTK_WINDOW (window), "MenuButton Example");
    gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);

    menubutton = gtk_menu_button_new ();
    gtk_widget_set_size_request (menubutton, 80, 35);

    gtk_grid_attach (GTK_GRID (grid), menubutton, 0, 0, 1, 1);
    gtk_container_add (GTK_CONTAINER (window), grid);

    menumodel = g_menu_new ();
    g_menu_append (menumodel, "New", "app.new");
    g_menu_append (menumodel, "About", "win.about");

    submenu = g_menu_new ();
    g_menu_append_submenu (menumodel, "Other", G_MENU_MODEL (submenu));
    g_menu_append (submenu, "Quit", "app.quit");
    gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (menubutton), G_MENU_MODEL (menumodel));

    about_action = g_simple_action_new ("about", NULL);
    g_signal_connect (about_action, "activate", G_CALLBACK (about_callback),
                    GTK_WINDOW (window));
    g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (about_action));

    gtk_widget_show_all (window);
    // not used
    (void)user_data;

}

static void startup (GApplication *app, gpointer      user_data)
{
    GSimpleAction *new_action;
    GSimpleAction *quit_action;

    new_action = g_simple_action_new ("new", NULL);
    g_signal_connect (new_action, "activate", G_CALLBACK (new_callback), app);
    g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (new_action));

    quit_action = g_simple_action_new ("quit", NULL);
    g_signal_connect (quit_action, "activate", G_CALLBACK (quit_callback), app);
    g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (quit_action));
    // not used
    (void)user_data;
}

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

    app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    g_signal_connect (app, "startup", G_CALLBACK (startup), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);
    return status;
}


第一个代码对我来说运行正常。

在第二步中,我尝试使用gtk_window和不使用GtkApplication进行相同的操作
请找到以下代码

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

//menubuttonexample_ter.c
/*  Compile with:
 *  gcc -std=c11 -Wall -fmax-errors=10 -Wextra menubuttonexample_ter.c -o menubuttonexample_ter `pkg-config --cflags --libs gtk+-3.0 `
 */

 /** le même que menubuttonexample mais en version non Gtkapplication */

/* Callback function for the undo action */
static void about_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    g_print ("You clicked \"About\"\n");
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}
static void new_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    g_print ("You clicked \"New\"\n");
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}

static void quit_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    GApplication *application = user_data;
    g_application_quit (application);
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}

static GActionGroup * create_action_group (void)
{
  const GActionEntry entries[] = {
    { "win.quit",         quit_callback, NULL, NULL, NULL,{0,0,0} },
    { "win.new",         new_callback, NULL, NULL, NULL,{0,0,0} },
    { "win.about", about_callback ,NULL, NULL, NULL,{0,0,0} }
  };
  GSimpleActionGroup *group;

  group = g_simple_action_group_new ();
  g_action_map_add_action_entries (G_ACTION_MAP (group), entries, G_N_ELEMENTS (entries), NULL);

  return G_ACTION_GROUP (group);
}

static GtkWidget* create_main_window (void)
{
    GMenu *submenu;
    GtkWidget *grid;
    GMenu *menumodel;
    GtkWidget *window;
    GtkWidget *menubutton;

    //GSimpleAction *about_action;
    //GSimpleAction *new_action;
    //GSimpleAction *quit_action;

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "MenuButton Example");
    gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);


    #define G_MENU_ATTRIBUTE_ACTION "win"

    GActionGroup * group = NULL;

    group = create_action_group(); // I don't know to link Gmenu and group


    /* Lorsque le shell affiche le menu de l'application, les actions de type "win"font référence à la copie
     * de cette action sur la fenêtre actuellement active.
     * Si une telle action n'existe pas, l'élément de menu sera grisé.
     * ===> c'est exactement ce que je constate à date */

    grid = gtk_grid_new ();

    menubutton = gtk_menu_button_new ();
    gtk_widget_set_size_request (menubutton, 80, 35);


    /*  essai */
    gtk_widget_map(GTK_WIDGET(menubutton));

    gtk_grid_attach (GTK_GRID (grid), menubutton, 0, 0, 1, 1);
    gtk_container_add (GTK_CONTAINER (window), grid);

    menumodel = g_menu_new ();
    g_menu_append (menumodel, "New", "win.new");
    g_menu_append (menumodel, "About", "win.about");

    submenu = g_menu_new ();
    g_menu_append_submenu (menumodel, "Other", G_MENU_MODEL (submenu));
    // from the menu, we refer to the action as "app.quit" since we installed it on the application
    g_menu_append (submenu, "Quit", "win.quit");
    gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (menubutton), G_MENU_MODEL (menumodel));
    return window;
}

int main (int argc, char **argv)
{
    GtkWidget *window = NULL;

    /* Initialisation de GTK+ */
    gtk_init (&argc, &argv);
    g_print("Version de gtk: %d.%d.%d\n", gtk_major_version, gtk_minor_version, gtk_micro_version);

    /* Creation du conteneur principal */
    window = create_main_window();

    /* Affichage de la fenetre principale */
    gtk_widget_show_all (window);
    /* Lancement de la boucle principale */
    gtk_main ();
    return EXIT_SUCCESS;
}


表示信息的级别。好像还可以因为与第一个示例相同。
问题纯粹是功能性的。

我不喜欢如何将GAction或GActiongroup实例组与Gmenu链接为menumodel。

请帮忙,因为我有一天没有解决方案就用Google搜索

最佳答案

我发现解决方案只需要两个命令

/* Implémentation of  GActionMap interface */
    GActionGroup *actions =(GActionGroup*)g_simple_action_group_new ();
/* namespace "win" created and linked with action*/
    gtk_widget_insert_action_group (window, "win", actions);

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

//menubuttonexample_ter.c
/*  Compile with:
 *  gcc -std=c11 -Wall -fmax-errors=10 -Wextra menubuttonexample_ter.c -o menubuttonexample_ter `pkg-config --cflags --libs gtk+-3.0 `
 */
 /** le même que menubuttonexample mais en version non Gtkapplication */

/* Callback function for the undo action */
static void about_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    g_print ("You clicked \"About\"\n");
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}
static void new_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    g_print ("You clicked \"New\"\n");
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}

static void quit_callback (GSimpleAction *simple, GVariant *parameter, gpointer user_data)
{
    gtk_main_quit();
    // not used
    (void)simple;
    (void)parameter;
    (void)user_data;
}

static GtkWidget* create_main_window (void)
{
    GMenu *submenu;
    GtkWidget *grid;
    GMenu *menumodel;
    GtkWidget *window;
    GtkWidget *menubutton;

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (window), "MenuButton Example");
    gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);

    grid = gtk_grid_new ();

    menubutton = gtk_menu_button_new ();
    gtk_widget_set_size_request (menubutton, 80, 35);

    gtk_grid_attach (GTK_GRID (grid), menubutton, 0, 0, 1, 1);
    gtk_container_add (GTK_CONTAINER (window), grid);

    /* Implémentation de l'interface GActionMap, une interface exposant un mappage de noms d'action à des GActions*/
    GActionGroup *actions =(GActionGroup*)g_simple_action_group_new ();
    /* création de l'espace de nom "win" qui va lier les actions et le widget principal window */
    gtk_widget_insert_action_group (window, "win", actions);

    const GActionEntry entries[] = {
        { "quit", quit_callback, NULL, NULL, NULL,{0,0,0} },
        { "new",  new_callback, NULL, NULL, NULL,{0,0,0} },
        { "about", about_callback ,NULL, NULL, NULL,{0,0,0} }
    };

    g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), window);

    /** partie couche de présentation **/
    /* création du premier menu */
    menumodel = g_menu_new ();

    g_menu_append (menumodel, "New", "win.new");
    g_menu_append (menumodel, "About","win.about");

    /** le sous-menu **/
    submenu = g_menu_new ();
    g_menu_append_submenu (menumodel, "Other", G_MENU_MODEL (submenu));
    g_menu_append (submenu, "Quit", "win.quit");
    /** association du menu au GtkMenuButton **/
    gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (menubutton), G_MENU_MODEL (menumodel));

    return window;
}

int main (int argc, char **argv)
{
    GtkWidget *window = NULL;
    /* Initialisation de GTK+ */
    gtk_init (&argc, &argv);
    g_print("Version de gtk: %d.%d.%d\n", gtk_major_version, gtk_minor_version, gtk_micro_version);
    /* Creation du conteneur principal */
    window = create_main_window();
    /* Affichage de la fenetre principale */
    gtk_widget_show_all (window);
    /* Lancement de la boucle principale */
    gtk_main ();
    return EXIT_SUCCESS;
}

10-04 21:57