寻找GtkWidget的孩子

Jon*_*erg 13 gtk ui-automation

我需要能够以编程方式探索GTK GUI的结构.我有GtkWidget,我想找到那个小部件的任何孩子.现在我知道GtkContainer有一个查找子项的功能,而GtkContainer是从GtkWidget派生的.

无论如何我可以检查一个小部件是否是一个GtkContainer,然后执行演员表?如果没有,有没有其他方式我可以发现GtkWidget是我的孩子?

pto*_*ato 14

是的,每个GObject类型都有宏来检查对象是否属于该类型:

if(GTK_IS_CONTAINER(widget)) {
    GList *children = gtk_container_get_children(GTK_CONTAINER(widget));
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果小部件是a,GtkBin它只有一个孩子.在这种情况下,以下内容比处理以下内容更简单GList:

if(GTK_IS_BIN(widget)) {
    GtkWidget *child = gtk_bin_get_child(GTK_BIN(widget));
    ...
}
Run Code Online (Sandbox Code Playgroud)


Dar*_*kas 5

在下面的代码中,我实现了一个find_child函数,该函数按名称递归搜索小部件.想法建立在@ptomato的答案之上,并且来自以下 PHP示例:

    #include <gtk/gtk.h>

    GtkWidget*
    find_child(GtkWidget* parent, const gchar* name)
    {
            if (g_strcasecmp(gtk_widget_get_name((GtkWidget*)parent), (gchar*)name) == 0) { 
                    return parent;
            }

            if (GTK_IS_BIN(parent)) {
                    GtkWidget *child = gtk_bin_get_child(GTK_BIN(parent));
                    return find_child(child, name);
            }

            if (GTK_IS_CONTAINER(parent)) {
                    GList *children = gtk_container_get_children(GTK_CONTAINER(parent));
                    while ((children = g_list_next(children)) != NULL) {
                            GtkWidget* widget = find_child(children->data, name);
                            if (widget != NULL) {
                                    return widget;
                            }
                    }
            }

            return NULL;
    }

    int
    main(int argc, char *argv[])
    {
            gtk_init(&argc, &argv);

            GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
            GtkWidget *frame = gtk_frame_new(NULL);
            GtkWidget *vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
            GtkWidget *textView = gtk_text_view_new();
            GtkWidget *hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
            GtkWidget *button1 = gtk_button_new_with_label("button1");
            gtk_widget_set_name(button1, "btn1");
            GtkWidget *button2 = gtk_button_new_with_label("button2");
            gtk_widget_set_name(button2, "btn2");

            gtk_window_set_title(GTK_WINDOW(window), "Hello");
            gtk_container_set_border_width(GTK_CONTAINER(window), 10);
            gtk_window_set_default_size(GTK_WINDOW(window), 450, 400);

            gtk_container_add(GTK_CONTAINER(window), frame);
            gtk_container_add(GTK_CONTAINER(frame), vbox1);

            gtk_box_pack_start(GTK_BOX(vbox1), textView, 1, 1, 0);
            gtk_box_pack_start(GTK_BOX(vbox1), hbox1, 0, 1, 0);
            gtk_box_pack_start(GTK_BOX(hbox1), button1, 0, 1, 0);
            gtk_box_pack_start(GTK_BOX(hbox1), button2, 0, 1, 0);

            gtk_widget_show_all(window);

            g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

            GtkWidget* child = find_child(window, "btn2");
            if (child == button2) {
                    g_print("found it!\n");
            } else {
                    g_print("not found it!\n");
            }

            gtk_main();
            return 0;
    }
Run Code Online (Sandbox Code Playgroud)

  • 感谢代码,它非常有帮助,帮助我解决了我的问题.但是,我发现了一个我想与使用它的人分享的错误:因为在find_child中你调用gtk_container_get_children()然后立即调用g_list_next_children(),你永远不会探索树中的第一个节点.我用do/while循环修复了这个问题,尽管你仍然需要确保第一个项目不是NULL. (2认同)