当我使用 pthread 时,新的 window 没有打开
new window does not open when i use pthread
我正在尝试制作一个聊天应用程序 (IRC),但在使用图形用户界面时,我无法同时显示新的 window 和 运行 客户端,服务器运行s 在控制台上完美。如果我尝试在没有服务器的情况下 运行 一个新的 window 它工作正常。我想打开一个新的 window 和 运行 客户端,以便它可以在最近打开的 window 上创建文本。
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 也有几个 pthread。
有什么办法可以同时 运行 launchClient 和一个新的 window 吗?
而且,从launchClient到运行recieved_text?
谢谢
在 GTK 中,您必须从主线程仅更新 GUI(即调用与小部件相关的 API)。你可以从其他线程做任何你想做的事,但是每当你需要更新用户界面时,你应该通知主线程,只有在那里 GUI 才会更新。
通知步骤非常容易完成,因为底层 GLib API 是 thread-aware,即 GLib 在请求时处理 locking/unlocking 内部数据。有很多方法可以做到这一点:我知道最简单的方法是使用 g_idle_add
(gdk_threads_add_idle
只是出于遗留原因保留的包装器)。
在 中,我提供了一个包含 100 个并发线程的基本示例,用于更新单个小部件。
我正在尝试制作一个聊天应用程序 (IRC),但在使用图形用户界面时,我无法同时显示新的 window 和 运行 客户端,服务器运行s 在控制台上完美。如果我尝试在没有服务器的情况下 运行 一个新的 window 它工作正常。我想打开一个新的 window 和 运行 客户端,以便它可以在最近打开的 window 上创建文本。
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 也有几个 pthread。 有什么办法可以同时 运行 launchClient 和一个新的 window 吗? 而且,从launchClient到运行recieved_text?
谢谢
在 GTK 中,您必须从主线程仅更新 GUI(即调用与小部件相关的 API)。你可以从其他线程做任何你想做的事,但是每当你需要更新用户界面时,你应该通知主线程,只有在那里 GUI 才会更新。
通知步骤非常容易完成,因为底层 GLib API 是 thread-aware,即 GLib 在请求时处理 locking/unlocking 内部数据。有很多方法可以做到这一点:我知道最简单的方法是使用 g_idle_add
(gdk_threads_add_idle
只是出于遗留原因保留的包装器)。
在