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
相关产品推荐
相关产品推荐

