c - 当我使用 pthread 时,新窗口不会打开

标签 c multithreading pthreads gtk glade

我正在尝试制作一个聊天应用程序(IRC),在使用 GUI 时我无法显示新窗口并同时运行客户端,服务器在控制台上完美运行。如果我尝试在没有服务器的情况下运行一个新窗口,它工作正常。我想打开一个新窗口并运行客户端,以便它可以在最近打开的窗口上创建文本。

void on_login_clicked(int argc, char *argv[])
{ 
    char userlogin[20];
    char userpass[20];
    sprintf(userlogin,"%s",user_text );
    sprintf(userpass,"%s",pass_text );

    printf ("Entry contents: %s\n", userlogin);
    printf ("Entry contents: %s\n", userpass);

    struct userData *acc = malloc(sizeof(struct userData));
    char ipadd[] = "0.0.0.0";

    acc = login(userlogin, userpass);
    if(acc == NULL)
        errx(1,"Your account does not exist!");


    system("clear");

    struct sentDATA *data = malloc(sizeof(struct sentDATA));
    data->acc = acc;
    data->adressIP = ipadd;


    gtkstartnewwindow(argc,argv, data);
}

void gtkstartnewwindow(int argc, char *argv[],struct sentDATA *data)
{


    GtkWidget *window;
    GtkWidget *mainBox;
    GtkWidget *grid;
    GtkWidget *topBox;
    GtkWidget *botBox;
    GtkWidget *header;

    GtkWidget *name;
    GtkWidget *entry;   
    GtkWidget *message;
    GtkWidget *connectBtn;
    GtkWidget *imgBtn;
    GtkWidget *callBtn;

    connected = FALSE;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_widget_set_size_request (window, 400, 500);

    gtk_window_set_title(GTK_WINDOW(window), "Chat client");

    mainBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);

    header = gtk_header_bar_new();

    name = gtk_label_new("");
    gtk_header_bar_set_custom_title(GTK_HEADER_BAR(header), name);

    connectBtn = gtk_button_new_with_label("Connect");
    gtk_widget_set_size_request(connectBtn, 70, 30);
    imgBtn = gtk_button_new_with_label("Send an image");
    gtk_widget_set_size_request(imgBtn, 70, 30);
    callBtn = gtk_button_new_with_label("Call someone");
    gtk_widget_set_size_request(callBtn, 70, 30);
    gtk_header_bar_pack_end(GTK_HEADER_BAR(header), imgBtn);
    gtk_header_bar_pack_start(GTK_HEADER_BAR(header), connectBtn);

    gtk_box_pack_start(GTK_BOX(mainBox), header, FALSE, FALSE, 0);

    grid = gtk_grid_new();
    gtk_grid_set_column_spacing (GTK_GRID(grid), 15);
    gtk_grid_set_row_spacing(GTK_GRID(grid), 5);

    gtk_container_set_border_width(GTK_CONTAINER(grid), 15);

    topBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3);
    gtk_widget_set_hexpand(topBox, TRUE);


    chat = gtk_text_view_new();
    gtk_text_view_set_editable(GTK_TEXT_VIEW(chat), FALSE);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(chat), FALSE);
    gtk_widget_set_vexpand (chat, TRUE);
    gtk_widget_set_hexpand (chat, TRUE);
    gtk_grid_attach(GTK_GRID(grid), chat, 0, 0, 1, 1);


    botBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3);
    message = gtk_text_view_new();
    gtk_widget_set_size_request(message, 70, 30);
    gtk_widget_set_hexpand (message, TRUE); 


    gtk_grid_attach(GTK_GRID(grid), botBox, 0, 2, 2, 1);
    gtk_widget_set_vexpand (grid, TRUE);
    gtk_widget_set_hexpand (grid, TRUE);
    gtk_widget_set_halign (grid, GTK_ALIGN_FILL);
    gtk_widget_set_valign (grid, GTK_ALIGN_FILL);

    gtk_box_pack_start(GTK_BOX(mainBox), grid, TRUE, TRUE, 0);
    gtk_container_add(GTK_CONTAINER(window), mainBox);

         entry = gtk_entry_new ();
    gtk_entry_set_max_length (GTK_ENTRY (entry), 50);
    g_signal_connect (entry, "activate",G_CALLBACK (enter_callback), entry);
    gtk_entry_set_text (GTK_ENTRY (entry), "hello");    
    g_signal_connect(imgBtn, "clicked", G_CALLBACK (on_open_image), NULL);
    gtk_grid_attach(GTK_GRID(grid), entry, 0 , 1, 2, 1);

    //g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window));
    gboolean runtime = TRUE;
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(exit_app), &runtime);

    gtk_widget_show_all(window);

    g_message("GUI started");


    while (gtk_main_iteration_do(FALSE)) {
        if (!runtime)
            break;
        //other callback handling

        //this loop needs to be running infinitely, 
        //if you need to wait in your program anywhere, 
        //(and it cannot be done only once before the loop)
        //we will need to make it into threads

    }

    pthread_t thr1;
    pthread_create(&thr1,NULL,launchClient,data);   
    pthread_join(thr1,NULL);
}



void recieved_text (gchar *m) {
    GtkTextIter e;

    GtkTextBuffer *chatBuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(chat));
    gtk_text_buffer_get_end_iter(chatBuf, &e);
    gtk_text_buffer_insert(chatBuf, &e, m, -1);
    gtk_text_buffer_insert(chatBuf, &e, "\n", 1);
} 


launchClient 还有几个 pthreads。 有没有办法同时运行 launchClient 和新窗口? 此外,要从 launchClient 运行 receive_text 吗?

谢谢

最佳答案

在 GTK 中,您必须从主线程更新 GUI(即调用小部件相关的 API)。您可以从其他线程执行任何您想要的操作,但是每当您需要更新用户界面时,您应该通知主线程,并且只有在那里 GUI 才会更新。

通知步骤非常容易完成,因为底层 GLib API 是线程感知的,即 GLib 在请求时负责锁定/解锁内部数据。有很多方法可以做到这一点:我知道的最简单的方法是使用 g_idle_add (gdk_threads_add_idle 只是出于遗留原因而保留的包装器)。

this answer我提供了一个基本示例,其中包含 100 个并发线程,用于更新单个小部件。

关于c - 当我使用 pthread 时,新窗口不会打开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56224969/

相关文章:

c - 当线程释放它的资源

c++ - 命名空间和 c++/c 混合 header

直接调用readline()的Tab补全

c - 操作数的评估顺序

objective-c - 在串口上用read()操作取消线程

java - Spring MVC 请求/ session 作用域 bean 线程安全

c# - AutoResetEvent 在信号前触发

c - pthread_attr_setschedparam() 返回非零但 errno = 成功 ...(Linux、C、Ubuntu 18.04.4)

c - 如何检查 __builtin_ 函数在 gcc 上是否可用

c - 对线程无效使用 void 表达式 (C)