当前位置: 技术问答>linux和unix
gtk中如何让另一个线程向GUI线程发送自定义消息?
来源: 互联网 发布时间:2016-10-25
本文导语: 以前没做过gtk的程序,现在有这样一个需求。 linux下的一个gtk程序,它总共有两个线程,一个主线程,一个工作线程。(按照windows上的开发经验,我姑且这样描述) 工作线程一直在后台运行,它在处理完某些事情...
以前没做过gtk的程序,现在有这样一个需求。
linux下的一个gtk程序,它总共有两个线程,一个主线程,一个工作线程。(按照windows上的开发经验,我姑且这样描述)
工作线程一直在后台运行,它在处理完某些事情后需要告知用户(在GUI上显示相关结果)。
以前我在windows上是这样实现的,当工作线程需要告知用户一些信息时,就发送自定义消息给GUI线程,GUI线程相应的消息接收函数会根据接收到的消息来更新GUI界面。
我现在也想在gtk中实现类似于windows上面的这种设计,gtk上全是回调,本人对它的机制还不是太清楚,只是觉得它要么是select,要么就poll了一些设备文件(鼠标,键盘)来响应用户的输入,可对于这种另外一个线程发起的消息(也许应该叫事件,信号)的处理,我找来找去也没找到相应的方法,希望大家能指点一下。
linux下的一个gtk程序,它总共有两个线程,一个主线程,一个工作线程。(按照windows上的开发经验,我姑且这样描述)
工作线程一直在后台运行,它在处理完某些事情后需要告知用户(在GUI上显示相关结果)。
以前我在windows上是这样实现的,当工作线程需要告知用户一些信息时,就发送自定义消息给GUI线程,GUI线程相应的消息接收函数会根据接收到的消息来更新GUI界面。
我现在也想在gtk中实现类似于windows上面的这种设计,gtk上全是回调,本人对它的机制还不是太清楚,只是觉得它要么是select,要么就poll了一些设备文件(鼠标,键盘)来响应用户的输入,可对于这种另外一个线程发起的消息(也许应该叫事件,信号)的处理,我找来找去也没找到相应的方法,希望大家能指点一下。
|
[code=C/C++]/*-------------------------------------------------------------------------
* Filename: gtk-thread.c
* Version: 1.99.1
* Copyright: Copyright (C) 1999, Erik Mouw
* Author: Erik Mouw
* Description: GTK threads example.
* Created at: Sun Oct 17 21:27:09 1999
* Modified by: Owen Taylor
* Modified at: Wed May 28 10:43:00 2003
*-----------------------------------------------------------------------*/
/*
* Compile with:
*
* cc -o gtk-thread gtk-thread.c `pkg-config --cflags --libs gtk+-2.0 gthread-2.0`
*
* Thanks to Sebastian Wilhelmi for pointing out some bugs in earlier versions.
*
*/
#include
#include
#define YES_IT_IS (1)
#define NO_IT_IS_NOT (0)
typedef struct
{
GtkWidget *label;
int what;
} yes_or_no_args;
G_LOCK_DEFINE_STATIC (yes_or_no);
static volatile int yes_or_no = YES_IT_IS;
void destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
}
void *argument_thread(void *args)
{
yes_or_no_args *data = (yes_or_no_args *)args;
gboolean say_something;
for(;;)
{
/* sleep a while */
sleep(g_random_int_range (1, 4));
/* lock the yes_or_no_variable */
G_LOCK(yes_or_no);
/* do we have to say something? */
say_something = (yes_or_no != data->what);
if(say_something)
{
/* set the variable */
yes_or_no = data->what;
}
/* Unlock the yes_or_no variable */
G_UNLOCK(yes_or_no);
if(say_something)
{
/* get GTK thread lock */
gdk_threads_enter();
/* set label text */
if(data->what == YES_IT_IS)
gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!");
else
gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!");
/* Make sure all X commands are sent to the X server; not strictly
* necessary here, but always a good idea when you do anything
* from a thread other than the one where the main loop is running.
*/
gdk_flush ();
/* release GTK thread lock */
gdk_threads_leave();
}
}
return NULL;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *label;
GError *error = NULL;
yes_or_no_args yes_args, no_args;
/* init threads */
g_thread_init(NULL);
gdk_threads_init();
/* init gtk */
gtk_init(&argc, &argv);
/* create a window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(window, "destroy",
G_CALLBACK(destroy), NULL);
gtk_container_set_border_width(GTK_CONTAINER (window), 10);
/* create a label */
label = gtk_label_new("And now for something completely different ...");
gtk_container_add(GTK_CONTAINER(window), label);
/* show everything */
gtk_widget_show(label);
gtk_widget_show (window);
/* create the threads */
yes_args.label = label;
yes_args.what = YES_IT_IS;
if (!g_thread_create(argument_thread, &yes_args, FALSE, &error))
{
g_printerr ("Failed to create YES thread: %sn", error->message);
return 1;
}
no_args.label = label;
no_args.what = NO_IT_IS_NOT;
if (!g_thread_create(argument_thread, &no_args, FALSE, &error))
{
g_printerr ("Failed to create NO thread: %sn", error->message);
return 1;
}
/* enter the GTK main loop */
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
return 0;
}
* Filename: gtk-thread.c
* Version: 1.99.1
* Copyright: Copyright (C) 1999, Erik Mouw
* Author: Erik Mouw
* Description: GTK threads example.
* Created at: Sun Oct 17 21:27:09 1999
* Modified by: Owen Taylor
* Modified at: Wed May 28 10:43:00 2003
*-----------------------------------------------------------------------*/
/*
* Compile with:
*
* cc -o gtk-thread gtk-thread.c `pkg-config --cflags --libs gtk+-2.0 gthread-2.0`
*
* Thanks to Sebastian Wilhelmi for pointing out some bugs in earlier versions.
*
*/
#include
#include
#define YES_IT_IS (1)
#define NO_IT_IS_NOT (0)
typedef struct
{
GtkWidget *label;
int what;
} yes_or_no_args;
G_LOCK_DEFINE_STATIC (yes_or_no);
static volatile int yes_or_no = YES_IT_IS;
void destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
}
void *argument_thread(void *args)
{
yes_or_no_args *data = (yes_or_no_args *)args;
gboolean say_something;
for(;;)
{
/* sleep a while */
sleep(g_random_int_range (1, 4));
/* lock the yes_or_no_variable */
G_LOCK(yes_or_no);
/* do we have to say something? */
say_something = (yes_or_no != data->what);
if(say_something)
{
/* set the variable */
yes_or_no = data->what;
}
/* Unlock the yes_or_no variable */
G_UNLOCK(yes_or_no);
if(say_something)
{
/* get GTK thread lock */
gdk_threads_enter();
/* set label text */
if(data->what == YES_IT_IS)
gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!");
else
gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!");
/* Make sure all X commands are sent to the X server; not strictly
* necessary here, but always a good idea when you do anything
* from a thread other than the one where the main loop is running.
*/
gdk_flush ();
/* release GTK thread lock */
gdk_threads_leave();
}
}
return NULL;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *label;
GError *error = NULL;
yes_or_no_args yes_args, no_args;
/* init threads */
g_thread_init(NULL);
gdk_threads_init();
/* init gtk */
gtk_init(&argc, &argv);
/* create a window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(window, "destroy",
G_CALLBACK(destroy), NULL);
gtk_container_set_border_width(GTK_CONTAINER (window), 10);
/* create a label */
label = gtk_label_new("And now for something completely different ...");
gtk_container_add(GTK_CONTAINER(window), label);
/* show everything */
gtk_widget_show(label);
gtk_widget_show (window);
/* create the threads */
yes_args.label = label;
yes_args.what = YES_IT_IS;
if (!g_thread_create(argument_thread, &yes_args, FALSE, &error))
{
g_printerr ("Failed to create YES thread: %sn", error->message);
return 1;
}
no_args.label = label;
no_args.what = NO_IT_IS_NOT;
if (!g_thread_create(argument_thread, &no_args, FALSE, &error))
{
g_printerr ("Failed to create NO thread: %sn", error->message);
return 1;
}
/* enter the GTK main loop */
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
return 0;
}
|
g_signal_new给你的your_widget加一个your_signal
g_signal_connect (your_widget, "your_signal", G_CALLBACK (your_callback), &your_parameters);
线程里适时g_signal_emit_by_name ((gpointer) your_widget, "your_signal");
your_callback和创建线程时都可传递参数
g_signal_connect (your_widget, "your_signal", G_CALLBACK (your_callback), &your_parameters);
线程里适时g_signal_emit_by_name ((gpointer) your_widget, "your_signal");
your_callback和创建线程时都可传递参数