c - 从线程调用时,GTK 代码挂起 @ gtk_container_add

标签 c gtk glib

我对 GTK 和 GLIB 非常陌生 我只是想显示图像,然后调用 disptext 函数。 但是当直接从 main 调用 disptextpage 函数时它可以工作,但是当我创建一个可以调用 disptextpage 的线程时它会卡在

gtk_container_add(GTK_CONTAINER(window), textv);

并且永远不会回来。 我犯的错误是什么

请指导:下面是示例代码:

    #include <stdio.h>
    #include <glib.h>
    #include <gtk/gtk.h>
    //#include "dispimage.h"
    #include <windows.h>
    #define sleep(n) Sleep(1000 * n)
    GtkWidget* window;
    void dispInit(int argc, char* argv[]);
    void dispInfoPage(char* fileName, int duration);


    gpointer main_callback(gpointer data)
    {
        gtk_main();
        return 0;
    }

    void dispInit(int argc, char* argv[])
    {
        gdk_threads_init();
        gdk_threads_enter();
        printf("Initializing the display library\n");
        gtk_init(&argc, &argv);
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_resize(GTK_WINDOW(window), 640, 480);
        gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
        gtk_widget_realize( window );
        gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
        g_thread_create(main_callback, NULL, FALSE, NULL);
        gdk_threads_leave();
    }

    void dispInfoPage(char* fileName, int duration)
    {
        int index;
        gdk_threads_enter();
        printf("Initializing dispInfoPage\n");
        destroyWidget();
        printf("Initializing dispInfoPage1\n");
        GtkWidget *image;
        image = gtk_image_new_from_file(fileName);
        printf("Initializing dispInfoPage2\n");
        gtk_container_add(GTK_CONTAINER(window), image);
        gtk_widget_show(image);
        gtk_widget_show(window);
        printf("Initializing dispInfoPage4\n");
        printf("Initializing dispInfoPage5\n");
        gdk_threads_leave();
        printf("Initializing dispInfoPage6\n");
    }

    void destroyWidget()
    {
        GList *children, *iter;
        struct WidgetsAlive *temp, *prev, *next, *depTemp;
        children = gtk_container_get_children(GTK_CONTAINER(window));
        for(iter = children; iter != NULL; iter = g_list_next(iter)){
            gtk_container_remove(GTK_CONTAINER(window),GTK_WIDGET(iter->data));
            printf("Deleting Widget\n");
        }
        g_list_free(iter);
        g_list_free(children);

    }


    int dispTextPage(char* fileName, int isJustifyCenter)
    {
        int index;
        GtkWidget *textv;
        GdkWindow *textv_window;
        GdkPixmap *pixmap = NULL;
        GtkTextBuffer *textBuffer;
        gdk_threads_enter();
        GdkColor color;
        char debugBuf[128] = { '\0' };
        char newfName[100]={'\0'};
        char ext[4]={'\0'};
        char temp[100]={'\0'};
        int i;
        FILE * fd;
        destroyWidget();
        textBuffer = gtk_text_buffer_new(NULL);
        textv = gtk_text_view_new_with_buffer(textBuffer);
        gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textv), 22);
        gtk_text_view_set_right_margin(GTK_TEXT_VIEW(textv), 20);
        gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(textv),1);
        gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textv), GTK_WRAP_CHAR);
        if (isJustifyCenter == 1)
        {
            gtk_text_view_set_justification(GTK_TEXT_VIEW(textv), GTK_JUSTIFY_CENTER);
        }
        else
        {
            gtk_text_view_set_justification(GTK_TEXT_VIEW(textv), GTK_JUSTIFY_LEFT);
        }
        gtk_text_view_set_editable(GTK_TEXT_VIEW(textv), FALSE);
        gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textv), FALSE);
        printf("tttt0");
        gtk_container_add(GTK_CONTAINER(window), textv);
        printf("tttt1");
        textv_window = gtk_text_view_get_window (GTK_TEXT_VIEW (textv),
                                               GTK_TEXT_WINDOW_TEXT);
        gdk_color_parse ("#68604d", &color);
        pixmap = gdk_pixmap_create_from_xpm ((GdkDrawable *) textv_window, NULL,
                                           &color, fileName);
        gdk_window_set_back_pixmap (textv_window, pixmap, FALSE);
        g_object_unref(pixmap);

        textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textv));

        gtk_text_buffer_create_tag (textBuffer, "Red", "foreground", "Red", NULL);
        gtk_text_buffer_create_tag (textBuffer, "RedBold","foreground", "Red",NULL);
          gtk_text_buffer_create_tag(textBuffer, "gray_bg", "background", "gray", NULL);
          gtk_text_buffer_create_tag(textBuffer, "italic",  "style", PANGO_STYLE_ITALIC, NULL);
          gtk_text_buffer_create_tag(textBuffer, "bold","weight", PANGO_WEIGHT_BOLD, NULL);
        gtk_text_buffer_create_tag (textBuffer, "RedFontWeight", "weight", 1000,NULL);
        gtk_text_buffer_create_tag (textBuffer, "RedBoldFontWeight","weight", 1000,NULL);
        gtk_widget_show(textv);
        gtk_widget_show(window);
        gdk_threads_leave();
        return index;
    }

    void *fsmThread_RunFunction()
    {
        int pollMsgRetVal = -1;
        printf("Now enter into for image");
        dispInfoPage("../images/givefp.gif",1);
        sleep(5);
        dispInfoPage("../images/bootup.gif",1);
        sleep(5);
        dispInfoPage("../images/givefp.gif",1);
        sleep(5);
        dispInfoPage("../images/bootup.gif",1);
        sleep(5);
        printf("Now enter into for disptext");
        dispTextPage("",0);
        printf("Now exit for disptext");
    }

    int main(int argc, char *argv[])
    {
        GThread *fsmThreadId;
        GError *error = NULL;
        g_thread_init(NULL);
        dispInit(argc, argv);
        dispInfoPage("../images/bootup.gif",1);
        sleep(5);
        printf("Now creat ethread ");
        fsmThreadId = g_thread_create(fsmThread_RunFunction,NULL,TRUE,&error);
        if (error) {
          fflush(stderr);
          exit(1);
        }
        g_thread_join(fsmThreadId);
        sleep(2);

        printf("ENd of main");
        return 0;
    }

最佳答案

所有 UI 操作/函数只能从一个线程调用。这是几乎所有(据我所知)UI 库(Gtk+、Qt、wxWidgets...)的常见 API 使用要求

只是不要这样做。使用工作线程,使用 g_idle_addg_timeout_add 并在那里进行(及时简短的)UI 修改。

关于c - 从线程调用时,GTK 代码挂起 @ gtk_container_add,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18432811/

相关文章:

c - g_main_loop 在 gtk 编程中如何工作?

c - 当我需要请求文件路径时如何使用 fopen_s?

从 Linux 编译适用于 Windows 的 GTK+ 应用程序

工具栏中的组合框

python - 用 Popen 模仿 glib.spawn 异步...

c - 在 glib 中打印 utf8

c++ - 通过 0.0 时减去 float 时出错

c++ - 在 Visual C++ 中接受来自客户端(套接字编程)的连接的问题

c - 未声明的变量。 [标题问题]

python - 'gi.repository.Gtk' 对象没有属性 'gdk'