GTK4中GtkPopoverMenuBar编译报错问题求助
我正在基于GTK4教程开发C语言应用,使用GtkPopoverMenuBar组件,但编译时GCC提示identifier "GtkPopoverMenuBar" is undefined,无法识别gtk/gtkpopovermenubar.h。
当前代码
#include <gtk/gtk.h> static void quit_activated(GSimpleAction *action, GVariant *parameter, GApplication *application) { g_application_quit (application); } static void app_activate (GApplication *application) { GtkApplication *app = GTK_APPLICATION (application); 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); gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE); gtk_window_present (GTK_WINDOW (win)); } static void app_startup (GApplication *application) { GtkApplication *app = GTK_APPLICATION (application); //GtkWidget *win = GTK_WIDGET(gtk_application_get_active_window(app)); //GtkWidget *boxv = gtk_window_get_child(GTK_WINDOW(win)); 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), application); GMenu *menubar = g_menu_new (); GtkPopoverMenuBar *popover_menubar = gtk_popover_menu_bar_new_from_model (menubar); GMenuItem *menu_item_file = g_menu_item_new ("File", 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_file, G_MENU_MODEL (menu)); g_menu_append_item (menubar, menu_item_file); g_object_unref (menu_item_file); //gtk_box_pack_start(GTK_BOX(boxv), GTK_WIDGET(popover_menubar), TRUE, FALSE, 0); gtk_application_set_menubar (GTK_APPLICATION (app), G_MENU_MODEL (menubar)); } #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_DEFAULT_FLAGS); g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL); 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; }
VSCode tasks.json配置
{ "tasks": [ { "type": "cppbuild", "label": "C/C++: gcc.exe build active file", "command": "C:\\msys64\\mingw64\\bin\\gcc.exe", "args": [ "-fdiagnostics-color=always", "-g", "-IC:/msys64/mingw64/bin/../include/libadwaita-1", "-IC:/msys64/mingw64/bin/../include/gtk-4.0", "-IC:/msys64/mingw64/bin/../include/pango-1.0", "-IC:/msys64/mingw64/bin/../include", "-IC:/msys64/mingw64/bin/../include/glib-2.0", "-IC:/msys64/mingw64/bin/../lib/glib-2.0/include", "-IC:/msys64/mingw64/bin/../include/harfbuzz", "-IC:/msys64/mingw64/bin/../include/freetype2", "-IC:/msys64/mingw64/bin/../include/libpng16", "-IC:/msys64/mingw64/bin/../include/fribidi", "-IC:/msys64/mingw64/bin/../include/cairo", "-IC:/msys64/mingw64/bin/../include/pixman-1", "-IC:/msys64/mingw64/bin/../include/gdk-pixbuf-2.0", "-IC:/msys64/mingw64/bin/../include/webp", "-IC:/msys64/mingw64/bin/../include/graphene-1.0", "-IC:/msys64/mingw64/bin/../lib/graphene-1.0/include", "${file}", "-LC:/msys64/mingw64/bin/../lib", "-ladwaita-1", "-lgtk-4", "-lpangowin32-1.0", "-lpangocairo-1.0", "-lpango-1.0", "-lharfbuzz", "-lgdk_pixbuf-2.0", "-lcairo-gobject", "-lcairo", "-lgraphene-1.0", "-lgio-2.0", "-lgobject-2.0", "-lglib-2.0", "-lintl", "-o", "${fileDirname}\\..\\bin\\${fileBasenameNoExtension}.exe" ], "options": { "cwd": "${fileDirname}" }, "problemMatcher": [ "$gcc" ], "group": { "kind": "build", "isDefault": true }, "detail": "Task generated by Debugger." } ], "version": "2.0.0" }
解决方案
检查GTK4版本:GtkPopoverMenuBar是GTK 4.10及以上版本新增的组件,先通过
pkg-config --modversion gtk4命令查看当前安装的GTK4版本。如果版本低于4.10,需要通过MSYS2的包管理器升级GTK4(执行pacman -S mingw-w64-x86_64-gtk4)。修正代码逻辑:你当前代码同时混用了传统应用菜单栏和GtkPopoverMenuBar,二者不可同时使用。若要使用GtkPopoverMenuBar,需调整代码:
- 删除
gtk_application_set_menubar的调用 - 在
app_activate函数中创建垂直容器并添加到窗口,再将GtkPopoverMenuBar放入容器:static void app_activate (GApplication *application) { GtkApplication *app = GTK_APPLICATION (application); 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); // 创建垂直容器 GtkWidget *boxv = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_window_set_child(GTK_WINDOW(win), boxv); // 移动GtkPopoverMenuBar的创建逻辑到此处(或确保窗口已创建后再执行) GMenu *menubar = g_menu_new (); GtkWidget *popover_menubar = gtk_popover_menu_bar_new_from_model (G_MENU_MODEL(menubar)); GMenuItem *menu_item_file = g_menu_item_new ("File", 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_file, G_MENU_MODEL (menu)); g_menu_append_item (menubar, menu_item_file); g_object_unref (menu_item_file); // 将菜单栏添加到容器(GTK4用gtk_box_append替代GTK3的gtk_box_pack_start) gtk_box_append(GTK_BOX(boxv), popover_menubar); gtk_window_present (GTK_WINDOW (win)); }
同时,将
app_startup中与菜单相关的代码移到app_activate(因为startup阶段窗口尚未创建),只保留动作注册的逻辑。- 删除
用pkg-config自动生成编译参数:手动指定include和link参数容易遗漏依赖,建议修改tasks.json的args部分,利用pkg-config自动获取正确参数:
"args": [ "-fdiagnostics-color=always", "-g", "${file}", "-o", "${fileDirname}\\..\\bin\\${fileBasenameNoExtension}.exe", "`pkg-config --cflags gtk4`", "`pkg-config --libs gtk4`" ]注意:需确保VSCode使用MSYS2的bash终端运行编译任务,否则无法解析命令替换。若用Windows cmd,可先执行
pkg-config --cflags gtk4和pkg-config --libs gtk4,将输出结果手动粘贴到args中。手动包含头文件:若版本达标仍报错,可尝试在代码开头手动添加
#include <gtk/gtkpopovermenubar.h>,确认系统中存在该头文件。如果找不到,说明GTK4安装不完整,需重新安装或升级。
内容的提问来源于stack exchange,提问作者Platinum Lucario

