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; }
问题原因及解决方法
核心原因
- 全局菜单栏的桌面环境差异:
gtk_application_set_menubar()设置的是应用全局菜单栏,GNOME等现代桌面环境会将其合并到系统顶部面板,而非窗口内部,导致你看到窗口空白但菜单实际在系统顶部。 - 资源提前释放(代码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
相关产品推荐
相关产品推荐

