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

Gtk4中如何按名称和类型查找GtkStack的子部件?

在Gtk4中按名称/类型查找子部件

我尝试从GtkStack中按名称或类型查找子部件。此前我使用如下在Gtk3中可正常运行的函数实现该功能:

GtkWidget* find_child_by_name (GtkWidget* parent, const gchar* name)
{
  printf("GtkWidget Name: %s\n\n", gtk_widget_get_name (parent));

    if (g_strcmp0(gtk_widget_get_name(parent), name) == 0)
        return parent;

    GList* children = NULL;
    if (GTK_IS_CONTAINER(parent))
        children = gtk_container_get_children(GTK_CONTAINER(parent));

    while (children != NULL)
    {
        GtkWidget* widget = find_child_by_name(children->data, name);

        if (widget != NULL)
            return widget;

        children = children->next;
    }
    return NULL;
}

但Gtk4中已移除gtk_container_get_children函数,我了解到gtk_widget_observe_children函数,但不清楚它的使用方法,请问在Gtk4中该如何实现按名称和类型查找子部件的功能?


一、按名称查找子部件

Gtk4中gtk_widget_observe_children()返回GListModel类型,而非Gtk3的GList,需要通过g_list_model_get_n_items()和g_list_model_get_item()遍历子部件。以下是适配后的递归查找函数:

#include <gtk/gtk.h>

GtkWidget* find_child_by_name(GtkWidget* parent, const gchar* name)
{
    // 检查当前部件是否匹配目标名称
    if (g_strcmp0(gtk_widget_get_name(parent), name) == 0)
        return parent;

    // 获取子部件列表模型
    GListModel* children_model = gtk_widget_observe_children(parent);
    gsize n_items = g_list_model_get_n_items(children_model);

    // 递归遍历所有子部件
    for (gsize i = 0; i < n_items; i++)
    {
        GtkWidget* child = GTK_WIDGET(g_list_model_get_item(children_model, i));
        GtkWidget* result = find_child_by_name(child, name);
        
        if (result != NULL)
        {
            g_object_unref(child); // 释放g_list_model_get_item获取的引用
            g_object_unref(children_model);
            return result;
        }
        g_object_unref(child);
    }

    g_object_unref(children_model);
    return NULL;
}

注意事项:

  • g_list_model_get_item()返回的对象带有引用计数,使用后必须调用g_object_unref()释放,避免内存泄漏
  • gtk_widget_observe_children()返回的模型同样需要用完后释放引用

二、按类型查找子部件

如果需要按GTK部件类型(如查找GtkButton或GtkStackPage),可以通过g_type_is_a()或GTK自带的类型宏判断,示例函数如下:

GtkWidget* find_child_by_type(GtkWidget* parent, GType target_type)
{
    // 检查当前部件是否匹配目标类型
    if (GTK_IS_WIDGET(parent) && g_type_is_a(G_OBJECT_TYPE(parent), target_type))
        return parent;

    GListModel* children_model = gtk_widget_observe_children(parent);
    gsize n_items = g_list_model_get_n_items(children_model);

    for (gsize i = 0; i < n_items; i++)
    {
        GtkWidget* child = GTK_WIDGET(g_list_model_get_item(children_model, i));
        GtkWidget* result = find_child_by_type(child, target_type);
        
        if (result != NULL)
        {
            g_object_unref(child);
            g_object_unref(children_model);
            return result;
        }
        g_object_unref(child);
    }

    g_object_unref(children_model);
    return NULL;
}

使用示例:

// 查找第一个GtkButton类型的子部件
GtkWidget* button = find_child_by_type(stack, GTK_TYPE_BUTTON);

三、GtkStack专属优化查找

如果明确是在GtkStack中查找,无需递归遍历,直接使用GtkStack的专属API更高效:

// 按名称直接查找GtkStack的子部件
GtkWidget* target_child = gtk_stack_get_child_by_name(GTK_STACK(stack), "your_target_name");

// 获取子部件对应的GtkStackPage(如果需要)
GtkStackPage* page = gtk_stack_get_page(GTK_STACK(stack), target_child);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:05:19