在GtkPopover中嵌入GtkText后自动隐藏失效等问题求助
在GtkPopover中使用GtkText组件的问题解决方法
问题描述
在GtkPopover中嵌入GtkText组件时遇到两个异常:
- 右键点击GtkText调用默认上下文菜单复制文本后,GtkPopover的自动隐藏功能失效,只能通过关闭父窗口来关闭弹窗;
- 当父窗口被其他应用窗口遮挡时,GtkText组件仍会显示在所有窗口最上层。
环境:Linux Lite 7.0(Xfce桌面)
问题原因
- GtkText的默认上下文菜单是独立顶层窗口,会干扰Popover的自动隐藏逻辑——点击菜单时Popover判定焦点仍在关联窗口内,不会触发隐藏;菜单关闭后,Popover也不会主动重新检查隐藏条件。
- 原代码中Popover与按钮的关联方式错误,导致GtkText的窗口层级没有正确继承Popover的属性,出现层级异常。
解决方案代码
#include <gtk/gtk.h> static void popup_cb (GtkButton *click, gpointer user_data) { if (GTK_IS_POPOVER(user_data)) gtk_popover_popup ((GtkPopover*)user_data); } static void on_text_menu_hide(GtkWidget *menu, gpointer popover) { // 菜单关闭后强制Popover重新检查自动隐藏条件 gtk_popover_set_autohide(GTK_POPOVER(popover), FALSE); gtk_popover_set_autohide(GTK_POPOVER(popover), TRUE); } static void activate (GtkApplication* app, gpointer user_data) { GtkWidget *window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "Window"); gtk_window_set_default_size (GTK_WINDOW (window), 200, 200); GtkWidget *fixed = gtk_fixed_new (); gtk_window_set_child (GTK_WINDOW (window), fixed); GtkWidget *fsBtn = gtk_button_new (); gtk_fixed_put ((GtkFixed *)fixed, fsBtn, 10, 10); gtk_widget_set_size_request(fsBtn, 30, 30); GtkWidget *grid = gtk_grid_new (); gtk_grid_set_row_spacing ((GtkGrid *)grid, 15); gtk_grid_set_column_homogeneous ((GtkGrid *)grid, FALSE); // 正确关联Popover到目标按钮,确保层级继承正确 GtkWidget *popover = gtk_popover_new (); gtk_popover_set_autohide ((GtkPopover *)popover, TRUE); gtk_popover_set_child ((GtkPopover*)popover, grid); gtk_popover_set_relative_to(GTK_POPOVER(popover), fsBtn); GtkWidget *preview_text = gtk_text_new(); gtk_editable_set_text ((GtkEditable *)preview_text, "Right Click & Copy text from GtkText"); gtk_widget_set_size_request(preview_text, 245, 50); gtk_grid_attach ((GtkGrid *)grid, preview_text, 0, 0, 1, 1); // 拦截默认菜单创建,手动绑定菜单关闭事件 g_signal_connect(preview_text, "popup-menu", G_CALLBACK(+[](GtkWidget *text, gint x, gint y, gboolean trigger, gpointer user_data) -> gboolean { GtkWidget *menu = gtk_text_create_context_menu(GTK_TEXT(text)); g_signal_connect(menu, "hide", G_CALLBACK(on_text_menu_hide), user_data); gtk_menu_popup_at_widget(GTK_MENU(menu), text, GDK_GRAVITY_SOUTH_WEST, GDK_GRAVITY_NORTH_WEST, NULL); return TRUE; // 阻止默认菜单流程 }), popover); g_signal_connect (fsBtn, "clicked", G_CALLBACK(popup_cb), popover); gtk_window_present (GTK_WINDOW (window)); } int main (int argc, char **argv) { GtkApplication *app; int status; #if GLIB_CHECK_VERSION(2, 74, 0) app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS); #else app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE); #endif g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); status = g_application_run (G_APPLICATION (app), argc, argv); g_object_unref (app); return status; }
修改说明
- 修复Popover关联方式:用
gtk_popover_set_relative_to替代gtk_widget_set_parent,让Popover正确绑定到按钮,确保内部GtkText组件继承Popover的窗口层级,解决父窗口被遮挡时GtkText仍顶层显示的问题。 - 修复自动隐藏失效:拦截GtkText的
popup-menu信号,手动创建上下文菜单并监听其hide事件。菜单关闭时,通过切换Popover的自动隐藏属性,强制它重新检查是否需要隐藏,恢复自动隐藏功能。
内容的提问来源于stack exchange,提问作者dibyendu
相关产品推荐
相关产品推荐

