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

GTK3窗口添加图片背景遮挡布局及控件问题咨询

问题现象
  • 基于GTK3编写带多层嵌套布局的窗口,主布局下的子布局均挂载了对应业务控件,尝试给窗口添加图片背景时,背景图片会遮挡主布局内所有其他布局与控件。
  • 同一份代码在GTK2环境下运行表现符合预期:子布局与控件均可正常显示在pixmap图层上方。
测试复现代码
GtkWidget*
create_wndmain (void)
{
  GtkWidget *wndmain;
  GtkWidget *lytmain;
  GtkWidget *lytpreview;
  GtkWidget *txtpreview;
  GtkWidget *lytutils;
  GtkWidget *txtutils;
  GtkWidget *lytfsys;
  GtkWidget *txtfsys;
  GtkWidget *pixmap;

  wndmain = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (wndmain), _("Window"));
  gtk_window_set_position (GTK_WINDOW (wndmain), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size (GTK_WINDOW (wndmain), 1024, 720);

  lytmain = gtk_layout_new (NULL, NULL);
  gtk_widget_show (lytmain);
  gtk_container_add (GTK_CONTAINER (wndmain), lytmain);

  pixmap = gtk_image_new_from_file("pixmaps/layout-1920x1080.png");
  gtk_container_add (GTK_CONTAINER (lytmain), pixmap);
  gtk_widget_show (pixmap);

  lytpreview = gtk_layout_new (NULL, NULL);
  gtk_widget_show (lytpreview);
  gtk_layout_put (GTK_LAYOUT (lytmain), lytpreview, 848, 88);
  gtk_widget_set_size_request (lytpreview, 168, 480);
  gtk_layout_set_size (GTK_LAYOUT (lytpreview), 400, 400);

  pixmap = gtk_image_new_from_file("pixmaps/layout-1920x1080.png");
  gtk_container_add (GTK_CONTAINER (lytpreview), pixmap);
  gtk_widget_show (pixmap);

  txtpreview = gtk_text_view_new ();
  gtk_widget_show (txtpreview);
  gtk_layout_put (GTK_LAYOUT (lytpreview), txtpreview, 8, 376);
  gtk_widget_set_size_request (txtpreview, 144, 80);
  gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (txtpreview)), _("\n\n        Preview Area"), -1);

  lytutils = gtk_layout_new (NULL, NULL);
  gtk_widget_show (lytutils);
  gtk_layout_put (GTK_LAYOUT (lytmain), lytutils, 664, 8);
  gtk_widget_set_size_request (lytutils, 344, 72);
  gtk_layout_set_size (GTK_LAYOUT (lytutils), 400, 400);

  txtutils = gtk_text_view_new ();
  gtk_widget_show (txtutils);
  gtk_layout_put (GTK_LAYOUT (lytutils), txtutils, 16, 8);
  gtk_widget_set_size_request (txtutils, 312, 56);
  gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (txtutils)), _("\n \tUtility Area"), -1);

  lytfsys = gtk_layout_new (NULL, NULL);
  gtk_widget_show (lytfsys);
  gtk_layout_put (GTK_LAYOUT (lytmain), lytfsys, 8, 88);
  gtk_widget_set_size_request (lytfsys, 192, 480);
  gtk_layout_set_size (GTK_LAYOUT (lytfsys), 400, 400);

  txtfsys = gtk_text_view_new ();
  gtk_widget_show (txtfsys);
  gtk_layout_put (GTK_LAYOUT (lytfsys), txtfsys, 32, 72);
  gtk_widget_set_size_request (txtfsys, 128, 328);
  gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (txtfsys)), _("\n\n\n    File system Area"), -1);

  return wndmain;
}


int
main (int argc, char *argv[])
{
  GtkWidget *wndmain;

  gtk_init (&argc, &argv);

  wndmain = create_wndmain ();
  gtk_widget_show (wndmain);

  gtk_main ();

  return 0;
}
问题原因

GTK2与GTK3的控件绘制逻辑存在本质差异:

  • GTK2版本的GtkLayout严格按照子控件添加顺序从底层到顶层绘制,先添加的pixmap处在最底层,后续添加的子布局、控件自然会叠加显示在背景上方。
  • GTK3重构了整个绘制栈与Z序排序规则,通过gtk_container_add添加到GtkLayout的子项,会被默认放置在Z序顶层,因此后添加的子布局、控件反而会被先加的背景图遮挡。
解决方案

提供两种可直接落地的修复方式:

  • 方案一:调整背景图添加逻辑
    不要用gtk_container_add添加背景图,统一用gtk_layout_put将背景图放置在布局的(0,0)坐标处,保证背景图是对应布局第一个通过gtk_layout_put添加的子项,同时设置背景图尺寸匹配布局大小即可。
    主布局背景的修改示例:
    // 注释掉原有错误写法
    // gtk_container_add (GTK_CONTAINER (lytmain), pixmap);
    // 替换为以下代码
    gtk_layout_put(GTK_LAYOUT(lytmain), pixmap, 0, 0);
    gtk_widget_set_size_request(pixmap, 1024, 720);
    
    子布局lytpreview内的背景图也做相同修改即可。
  • 方案二:使用GTK3官方推荐的CSS方式设置背景
    不需要额外创建GtkImage控件,直接通过CSS给布局设置背景属性,背景会自动作为容器底层绘制,完全不会出现Z序遮挡问题,是更规范的实现方式。示例代码:
    GtkCssProvider *bg_provider = gtk_css_provider_new();
    gtk_css_provider_load_from_data(bg_provider,
        "GtkLayout {"
        "  background-image: url('pixmaps/layout-1920x1080.png');"
        "  background-size: 100% 100%;"
        "  background-repeat: no-repeat;"
        "}", -1, NULL);
    gtk_style_context_add_provider(gtk_widget_get_style_context(lytmain),
        GTK_STYLE_PROVIDER(bg_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
    g_object_unref(bg_provider);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:12:14