You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GTK4菜单栏无法显示求助:两段代码仅生成空白窗口

GTK4菜单栏不显示问题排查

我尝试创建基础GTK4菜单栏,网上找的示例代码都能编译,但运行后菜单栏完全不显示,只弹出空白窗口。以下是两段测试代码:

测试代码1

#include <gtk/gtk.h>
  
static void
quit_activated(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
  GApplication *app = G_APPLICATION (user_data);

  g_application_quit (app);
}

static void
app_activate (GApplication *app, gpointer user_data) {
  GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
  gtk_window_set_title (GTK_WINDOW (win), "menu1");
  gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);

  GSimpleAction *act_quit = g_simple_action_new ("quit", NULL);
  g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_quit));
  g_signal_connect (act_quit, "activate", G_CALLBACK (quit_activated), app);

  GMenu *menubar = g_menu_new ();
  GMenuItem *menu_item_menu = g_menu_item_new ("Menu", NULL);
  GMenu *menu = g_menu_new ();
  GMenuItem *menu_item_quit = g_menu_item_new ("Quit", "app.quit");
  g_menu_append_item (menu, menu_item_quit);
  g_object_unref (menu_item_quit);
  g_menu_item_set_submenu (menu_item_menu, G_MENU_MODEL (menu));
  g_menu_append_item (menubar, menu_item_menu);
  g_object_unref (menu_item_menu);

  gtk_application_set_menubar (GTK_APPLICATION (app), G_MENU_MODEL (menubar));
  gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);
  gtk_window_present (GTK_WINDOW (win));
/*  gtk_widget_show (win); is also OKay instead of gtk_window_present. */
}

#define APPLICATION_ID "com.github.ToshioCP.menu1"

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

  app = gtk_application_new (APPLICATION_ID, G_APPLICATION_FLAGS_NONE);
  g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL);

  stat =g_application_run (G_APPLICATION (app), argc, argv);
  g_object_unref (app);
  return stat;
}

测试代码2

#include <gtk/gtk.h>

static void action_clbk ( GSimpleAction *simple_action, G_GNUC_UNUSED GVariant *parameter, G_GNUC_UNUSED gpointer *data )
{
    g_print ( "The action %s was clicked.\n", g_action_get_name ( G_ACTION ( simple_action ) ) );
}

static void activate ( GApplication *app, G_GNUC_UNUSED gpointer *data )
{
    GtkWidget *win;
    GSimpleAction *act_connect;
    GSimpleAction *act_disconnect;

    /// ***
    GMenu *menu_bar;
    GMenu *network_menu;
    GMenu *server_menu;

    /// ***
    GMenuItem *menu_item_connect;
    GMenuItem *menu_item_disconnect;

    /// *** Menu Bar
    menu_bar = g_menu_new();

    /// *** Network_Menu
    network_menu = g_menu_new();
    g_menu_append_submenu ( menu_bar, "Network", G_MENU_MODEL ( network_menu ) );

    /// *** Server_Menu
    server_menu = g_menu_new();
    g_menu_append_submenu ( network_menu, "Server", G_MENU_MODEL ( server_menu ) );
    /// ***
    win = gtk_application_window_new ( GTK_APPLICATION ( app ) );
    gtk_window_set_title ( GTK_WINDOW ( win ), "IRC Client" );
    gtk_window_set_default_size ( GTK_WINDOW ( win ), 400, 400 );

    /// *** Create Connect and Disconnect Actions
    act_connect    = g_simple_action_new ( "connect", NULL );
    act_disconnect = g_simple_action_new ( "disconnect", NULL );

    /// *** Add them to the ActionMap
    g_action_map_add_action ( G_ACTION_MAP ( app ), G_ACTION ( act_connect ) );
    g_action_map_add_action ( G_ACTION_MAP ( app ), G_ACTION ( act_disconnect ) );

    /// *** Connect them to the activate Signal
    g_signal_connect ( act_connect,    "activate", G_CALLBACK ( action_clbk ), NULL );
    g_signal_connect ( act_disconnect, "activate", G_CALLBACK ( action_clbk ), NULL );

    /// *** Create the Connect Item
    menu_item_connect = g_menu_item_new ( "Connect", "app.connect" );
    g_menu_append_item ( server_menu, menu_item_connect );

    /// *** Create the Disconnect Item
    menu_item_disconnect = g_menu_item_new ( "Disconnect", "app.disconnect" );
    g_menu_append_item ( server_menu, menu_item_disconnect );

    /// ***
    gtk_application_set_menubar             ( GTK_APPLICATION ( app ), G_MENU_MODEL ( menu_bar ) );
    gtk_application_window_set_show_menubar ( GTK_APPLICATION_WINDOW ( win ), TRUE );

    /// ***
    gtk_window_present ( GTK_WINDOW ( win ) );

    /// *** Clean
    g_object_unref ( act_connect );
    g_object_unref ( act_disconnect );
    g_object_unref ( menu_item_connect );
    g_object_unref ( menu_item_disconnect );
    g_object_unref ( server_menu );
    g_object_unref ( network_menu );
    g_object_unref ( menu_bar );
}

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

    /// ***
    app = gtk_application_new ( "com.ircclient", G_APPLICATION_FLAGS_NONE );
    g_signal_connect ( app, "activate", G_CALLBACK ( activate ), NULL );

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

    /// ***
    return stat;
}

问题原因及解决方法

核心原因

  1. 全局菜单栏的桌面环境差异:gtk_application_set_menubar()设置的是应用全局菜单栏,GNOME等现代桌面环境会将其合并到系统顶部面板,而非窗口内部,导致你看到窗口空白但菜单实际在系统顶部。
  2. 资源提前释放(代码2专属问题):代码2中在窗口显示前就手动释放了menu_bar、network_menu等GMenu对象,GTK需要这些对象保持引用才能渲染菜单,提前释放会导致菜单丢失。

解决办法

办法1:强制在窗口内显示菜单栏(兼容所有环境)

改用GtkPopoverMenuBar创建窗口内菜单栏,替代全局菜单栏设置:

// 修改代码1的app_activate函数中菜单相关代码为:
GMenu *menu = g_menu_new();
g_menu_append(menu, "Quit", "app.quit");

// 创建窗口内菜单栏并添加到窗口
GtkWidget *menubar = gtk_popover_menu_bar_new_from_model(G_MENU_MODEL(menu));
gtk_window_set_child(GTK_WINDOW(win), menubar);

// 移除以下两行全局菜单栏相关代码:
// gtk_application_set_menubar (GTK_APPLICATION (app), G_MENU_MODEL (menubar));
// gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);

办法2:修复全局菜单栏的资源释放问题(代码2)

删除代码2中activate函数末尾的菜单相关对象释放代码:

// 移除这些行:
// g_object_unref ( server_menu );
// g_object_unref ( network_menu );
// g_object_unref ( menu_bar );

gtk_application_set_menubar()会自动增加菜单模型的引用计数,无需手动提前释放,这样全局菜单栏就能在系统顶部正常显示。

额外调试技巧

编译时确保链接GTK4库,命令示例:

gcc -o menu_test menu_test.c `pkg-config --cflags --libs gtk4`

运行调试工具查看部件状态:

GTK_DEBUG=interactive ./menu_test

内容的提问来源于stack exchange,提问作者Shawn Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 14:06:18