在gtkdrawingarea中输入文字
时间:2010-10-17 来源:liudan0201
在游戏设计中,通常会用到drawing area构件,并在该构件上画图。而且为了让游戏更酷一点,通常不想用到比如entry,button之类的构件。而是希望能在drawing area上全部处理掉,但是如何在drawing area上直接输入文字?这2天,老农查了不少资料,做了不少实验,终于搞定,在此分享一下。
Gtk的输入主要用了GtkIMContext,GtkIMContext在gtk参考文档上是这样介绍的:
GtkIMContext defines the interface for GTK+ input methods. An input method is used by GTK+ text input widgets like GtkEntry to map from key events to Unicode character strings.
即:GtkIMContext是为GTK提供了一个输入的方法,而且GTK中的一些文字输入相关的构件(如:GtkEntry)都采用了这种方法。GtkIMContext能把key event转换成统一编码的字符串。
GtkIMContext的具体用法在网上很难找到。老农在goolge上找了大半天,未果,于是只能找些关于GTK的一些官方参考资料,但还是不太清楚。然而我们有一个线索,就是GtkEntry等构件就是用GtkIMContext进行输入的,所以,看看GtkEntry的源码,也许可以找到点线索。我想这就是开源的好处吧,当缺乏资料的时候,至少我们有源代码,那儿什么宝物都有,只要有耐心去找。
最后老农终于在GtkEntry的代码中,找到了GtkIMContext的用法。
首先定义一个GtkIMContext:
GtkIMContext *im_context;
再创建一个GtkIMContext,用gtk_im_multicontext_new()函数:
im_context= gtk_im_multicontext_new();
再给GtkIMContext加上一个回调函数:
g_signal_connect (im_context, "commit", G_CALLBACK (gtk_entry_commit_cb), NULL);
"commit"信号的说明:当用户输入一个完整的序列时,该信号被触发。输入可以是一个字符,也可以是一个字符串。(老农理解:当输入为英文字符或数字时,即为一个字符,当输入为中文字时,一次输入为一个字符串)
另外,还需要2个函数:
gtk_im_context_set_client_window(im_context, window->window);
gtk_im_context_focus_in (im_context);
第一个函数是把GtkIMContext和主窗口关联起来,第二个函数是把im_context设置成focus_in的,即输入焦点。
还没有结束,因为当按键时,GtkIMContext的"commit"是不会自动触发的,它需要另外一个函数来触发,gtk_im_context_filter_keypress()函数,如下:
gtk_im_context_filter_keypress (im_context, event);
第一个参数是im_context,第二个参数是key_press_event产生的GdkEventKey。
所以我们要给"key-press-event"加一个回调函数,把下面的语句放到main()函数gtk_main()之前:
g_signal_connect(window, "key-press-event", G_CALLBACK(main_key_press_event), NULL);
定义回调函数main_key_press_event()如下:
static gboolean main_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
gtk_im_context_filter_keypress (im_context, event);
return FALSE;
}
该回调函数只是调用了gtk_im_context_filter_keypress(),用于触发GtkIMContext的"commit"信号。最后定义"commit"信号的回调函数如下:
static void gtk_entry_commit_cb (GtkIMContext *context, const guchar *str, gpointer data)
{
int i;
int len, len_c;
len= strlen(str);
len_c= strlen(c_input)-1; //最后一个是'_'
for(i= 0; i< len; i++)
c_input[len_c+i]= *(str+i);
c_input[len_c+ len]= '_';
gtk_widget_queue_draw(draw_main);
}
c_input为输入的字符串。没有输入时,c_input有一个字符’_’,表示输入位置。每次输入的字符放在’_’的前面显示。字符的显示,用了Pango,代码如下,先不做解释:
gchar font[]= "Monospace Bold 15";
static void show_pictures(cairo_t *cr)
{
PangoLayout *layout;
PangoFontDescription *desc;
cairo_save(cr);
layout = pango_cairo_create_layout (cr);
pango_layout_set_text (layout, c_input, -1);
desc = pango_font_description_from_string (font);
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
cairo_set_source_rgba (cr, 0, 0, 1, 1);
pango_cairo_update_layout (cr, layout);
cairo_move_to (cr, 100, 100);
pango_cairo_show_layout (cr, layout);
cairo_restore(cr);
g_object_unref (layout);
}
看看效果(连中文也能显示噢):
GtkIMContext defines the interface for GTK+ input methods. An input method is used by GTK+ text input widgets like GtkEntry to map from key events to Unicode character strings.
即:GtkIMContext是为GTK提供了一个输入的方法,而且GTK中的一些文字输入相关的构件(如:GtkEntry)都采用了这种方法。GtkIMContext能把key event转换成统一编码的字符串。
GtkIMContext的具体用法在网上很难找到。老农在goolge上找了大半天,未果,于是只能找些关于GTK的一些官方参考资料,但还是不太清楚。然而我们有一个线索,就是GtkEntry等构件就是用GtkIMContext进行输入的,所以,看看GtkEntry的源码,也许可以找到点线索。我想这就是开源的好处吧,当缺乏资料的时候,至少我们有源代码,那儿什么宝物都有,只要有耐心去找。
最后老农终于在GtkEntry的代码中,找到了GtkIMContext的用法。
首先定义一个GtkIMContext:
GtkIMContext *im_context;
再创建一个GtkIMContext,用gtk_im_multicontext_new()函数:
im_context= gtk_im_multicontext_new();
再给GtkIMContext加上一个回调函数:
g_signal_connect (im_context, "commit", G_CALLBACK (gtk_entry_commit_cb), NULL);
"commit"信号的说明:当用户输入一个完整的序列时,该信号被触发。输入可以是一个字符,也可以是一个字符串。(老农理解:当输入为英文字符或数字时,即为一个字符,当输入为中文字时,一次输入为一个字符串)
另外,还需要2个函数:
gtk_im_context_set_client_window(im_context, window->window);
gtk_im_context_focus_in (im_context);
第一个函数是把GtkIMContext和主窗口关联起来,第二个函数是把im_context设置成focus_in的,即输入焦点。
还没有结束,因为当按键时,GtkIMContext的"commit"是不会自动触发的,它需要另外一个函数来触发,gtk_im_context_filter_keypress()函数,如下:
gtk_im_context_filter_keypress (im_context, event);
第一个参数是im_context,第二个参数是key_press_event产生的GdkEventKey。
所以我们要给"key-press-event"加一个回调函数,把下面的语句放到main()函数gtk_main()之前:
g_signal_connect(window, "key-press-event", G_CALLBACK(main_key_press_event), NULL);
定义回调函数main_key_press_event()如下:
static gboolean main_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
gtk_im_context_filter_keypress (im_context, event);
return FALSE;
}
该回调函数只是调用了gtk_im_context_filter_keypress(),用于触发GtkIMContext的"commit"信号。最后定义"commit"信号的回调函数如下:
static void gtk_entry_commit_cb (GtkIMContext *context, const guchar *str, gpointer data)
{
int i;
int len, len_c;
len= strlen(str);
len_c= strlen(c_input)-1; //最后一个是'_'
for(i= 0; i< len; i++)
c_input[len_c+i]= *(str+i);
c_input[len_c+ len]= '_';
gtk_widget_queue_draw(draw_main);
}
c_input为输入的字符串。没有输入时,c_input有一个字符’_’,表示输入位置。每次输入的字符放在’_’的前面显示。字符的显示,用了Pango,代码如下,先不做解释:
gchar font[]= "Monospace Bold 15";
static void show_pictures(cairo_t *cr)
{
PangoLayout *layout;
PangoFontDescription *desc;
cairo_save(cr);
layout = pango_cairo_create_layout (cr);
pango_layout_set_text (layout, c_input, -1);
desc = pango_font_description_from_string (font);
pango_layout_set_font_description (layout, desc);
pango_font_description_free (desc);
cairo_set_source_rgba (cr, 0, 0, 1, 1);
pango_cairo_update_layout (cr, layout);
cairo_move_to (cr, 100, 100);
pango_cairo_show_layout (cr, layout);
cairo_restore(cr);
g_object_unref (layout);
}
看看效果(连中文也能显示噢):
下载 (14.86 KB)
2010-7-5 08:30
来看看代码(现在代码只有输入,没有删除功能等):
readkey1.rar (1.09 KB)
来看看代码(现在代码只有输入,没有删除功能等):
readkey1.rar (1.09 KB)
相关阅读 更多 +