3

这是我对 GTK 理解的延续::

从 Main 调用 pthread 下的 GTK_MAIN() 是否正确?示例代码::

我调用dispInit(argc, argv); 我从中调用g_thread_create(main_callback, NULL, FALSE, NULL);

** 我也没有在此代码中包含 g_idle_add ..这只是一个参考代码。

请指导

#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;
}
4

1 回答 1

5

简短的回答:是的,您可以gtk_main()从主 C 线程以外的线程调用,只要您在整个进程的生命周期内始终从同一线程调用所有 GTK API 函数。更多细节如下。

根据文档,GTK 和 GDK 不是线程安全的(它们不能从多个线程同时调用),但它们是线程感知的——它们提供锁定功能,例如gdk_threads_entergdk_threads_leave,可用于跨多个线程同步 GTK 调用。但是,文档继续说“对于 Win32 后端,根本不应该从多个线程尝试 GDK 和 GTK+ 调用。” 因此,如果您关心 Windows 的可移植性,您将希望避免尝试从多个线程调用 GTK API 调用。此外,GTK 3 完全弃用了线程锁。

然而,有一种方法可以安全地从适用于所有架构的多个线程调用 GTK:将 GTK 调用放在一个函数中,并将其作为回调传递给g_idle_add(没有任何特殊锁定)——从任何线程。它将安排由 GTK 主循环调用的回调,在任何运行它的线程中。这记录在文档描述部分的末尾,在详细信息部分的开头上方。

关于术语:C 中的“主线程”一词通常指的是运行 Cmain()函数的线程。在 GTK 上下文中,“主线程”经常令人混淆地指代运行 GTK 主循环的线程。虽然两者可以(并且通常是)相同,但 GTK 并不真正关心您从哪个线程调用主循环,只要您gtk_main从同一个调用所有 GTK 函数(包括 )。为避免混淆,最好将此线程称为 GTK 线程、主循环线程或 GUI 线程。

于 2013-09-22T07:55:11.837 回答