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

GTK4中手动在Notebook间移动页面的实现问题求助

GTK Notebook页面跨容器移动问题解决方案

问题背景

开发GTK应用时,尝试将一个Notebook中的页面内容移动到另一个Notebook(如把notebook_1的页面移到notebook_2),但遇到两种错误:

  • 调用gtk_notebook_remove_page后,再调用gtk_notebook_append_page会触发断言错误:gtk_notebook_append_page: assertion 'GTK_IS_WIDGET (child)' failed,操作返回-1失败。
  • 注释移除语句后,触发父容器冲突错误:Duplicate child name in GtkStack: (null)和gtk_widget_set_parent: assertion '_gtk_widget_get_parent (widget) == NULL' failed,页面内容不显示。

核心原因

GTK容器通过引用计数管理子控件生命周期:当子控件从原Notebook移除时,gtk_notebook_remove_page会调用g_object_unref()减少引用计数。如果这是控件的最后一个引用,控件会被立即销毁,导致后续添加时引用无效;而不移除的话,控件仍属于原父容器,无法重复添加到新容器。

解决方法

在移除页面之前,手动增加目标子控件和标签的引用计数,确保移除后控件不会被销毁,再添加到新Notebook中。修改后的move_page函数如下:

/* move a page from notebook_1 to notebook_2 */
void move_page (GtkButton *button)
{
    gint page;
    GtkWidget *child;
    GtkWidget *label;
    
    page = gtk_notebook_get_current_page(notebook_1);
    child = gtk_notebook_get_nth_page(notebook_1, page);
    label = gtk_notebook_get_tab_label(notebook_1, child);

    // 增加引用计数,防止移除时销毁控件
    g_object_ref(child);
    g_object_ref(label);

    gtk_notebook_remove_page(notebook_1, page);
    
    // 添加到目标Notebook
    gtk_notebook_append_page(GTK_NOTEBOOK(notebook_2), child, label);

    // 可选:添加完成后释放手动增加的引用,避免内存泄漏
    g_object_unref(child);
    g_object_unref(label);
    
    gtk_widget_queue_draw(GTK_WIDGET(notebook_1));
    gtk_widget_queue_draw(GTK_WIDGET(notebook_2));
}

关键说明

  • g_object_ref():为控件增加一个引用,确保gtk_notebook_remove_page减少引用后,计数仍大于0,控件不会被销毁。
  • g_object_unref():添加到新Notebook后,新容器会自动为控件增加引用,此时可以释放手动添加的引用,避免内存泄漏(也可以不手动释放,因为控件被新容器持有,最终会随容器一起销毁)。
  • 需同时处理页面内容和标签控件,否则标签可能会被销毁导致新页面无标签。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:30:14