学习使用GTK+ 5.GTK+常用物件及API(文本)

来源:互联网 发布:以爆字为首的网络语言 编辑:程序博客网 时间:2024/05/21 22:38

学习使用GTK+ 5.GTK+常用物件及API(文本)

学习使用GTK+ 系列的第 6 篇 (本系列共6篇)
学习使用GTK+
  • 学习使用GTK+ 0.概述
  • 学习使用GTK+ 1.构建GTK+编译环境
  • 学习使用GTK+ 2.GTK+“Hello World”——对GTK+运作机制的通俗介绍
  • 学习使用GTK+ 3.使用GtkBuilder、界面设计器Glade和其他GTK+组件
  • 学习使用GTK+ 4.GTK+常用物件及API(窗口)
  • 学习使用GTK+ 5.GTK+常用物件及API(文本)

这一部分内容介绍有关GTK+常用文本类物件的一些函数。如果对内容有疑问,请在下方留言,谢谢!

GTK+的文本

显示文字和控制文本框自然是界面重头戏,基本每个窗口都离不开这样的物件。GTK+中和文本有关的物件主要有:文本标签(GtkLabel,以下简称“文本”),输入框(GtkEntry),可编辑多行文本(GtkTextView,以下简称“多行文本”),调节按钮(GtkSpinButton)。各物件有自己的优点。

  • 文本:简单地显示一些文字,使用非常方便,一般用于显示界面上最普通的文字。
  • 输入框:用于让用户输入一行文字,使用方便。
  • 多行文本:用于让用户输入多行文字,或显示一段非常长的文字,可配合滚动区(GtkScrolledWindow)使用来达到很好的显示效果,也可为部分文字设置样式。它的缺陷在于使用繁琐。
  • 调节按钮:用于输入数字,在控制数字输入方面的功能非常强大,其右侧有上下调节数字大小的按钮。

具体使用哪个物件需要根据实际情况决定。

访问文本、输入框

对文本类物件的操作基本相似。对这些物件的动态访问基本归结为以下两种——读取所包含的文字信息(读)、设置所包含的文字内容(写)。其他的设置基本不需要动态改变,初始时在Glade中设置好即可(如果真的需要修改,自己去看参考吧)。

下面这些函数用于对文本、输入框的读写,函数名字都很好记。

//写入文本内容
void gtk_label_set_text(GtkLabel *label, const gchar *str);
//读取文本内容
const gchar* gtk_label_get_text(GtkLabel *label);
//写入输入框内容
void gtk_entry_set_text(GtkEntry *entry, const gchar *text);
//读取输入框内容
const gchar* gtk_entry_get_text(GtkEntry *entry);

使用调节按钮

调节按钮是用于操作数字的,因而可以直接向其中写入或者读出实数或整数。

//设置调节按钮的数值
void gtk_spin_button_set_value (GtkSpinButton *spin_button, gdouble value);
//读出调节按钮的数值
gdouble gtk_spin_button_get_value (GtkSpinButton *spin_button);
gint gtk_spin_button_get_value_as_int(GtkSpinButton *spin_button);

做个实例吧。本系列第三部分做了一个计算器雏形,下面来稍稍完善一下。

计算器的上方有一个名为SAns的调节按钮,下面增加一个功能:当调节按钮的值的绝对值过大(大于等于常数CAL_ABS_MAX)时,弹出错误提示窗口。

每个调节按钮对应一个GtkAdjustment,首先应为调节按钮添加一个GtkAdjustment。在Glade中,点“常规”的“调整部件”右侧的“…”,弹出窗口中点“New”。

此时上方的物件选择栏末尾中会出现一个对象adjustment1,可以更改它的属性,即调节按钮的最值、步长等。

然后为SAns的信号value-changed添加操作句柄“on_SAns_value_changed”,然后在程序中添加相应回调函数。

回到程序中,在初始化时,用gtk_spin_button_set_range()修改调节按钮取值范围为[-CAL_ABS_MAX,CAL_ABS_MAX],再编写回调函数on_SAns_value_changed(),顺便用上上一部分写的函数gtk_show_error()。完整代码如下。

#include <gtk/gtk.h>
 
#define CAL_ABS_MAX 1e9
 
#define w_(builder,type,name) name=GTK_##type(gtk_builder_get_object(builder,#name))
 
GtkWindow *WMain;
GtkSpinButton *SAns;
 
//显示一个错误提示窗口
void gtk_show_error(gpointer window, const gchar* message, const gchar* title)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new_with_markup(window,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
message);
gtk_window_set_title(GTK_WINDOW(dialog), title);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
 
G_MODULE_EXPORT void on_SAns_value_changed(GtkObject* widget, gpointer user_data)
{
//gdouble在Windows下等价于double
gdouble d;
//读取调节按钮的值
d=gtk_spin_button_get_value(SAns);
//判断是否需要显示错误提示窗口
if(d>=CAL_ABS_MAX)
{
gtk_show_error(WMain,"Too Large","Error!");
//设置调节按钮值为零
gtk_spin_button_set_value(SAns,0);
}
else if(-d>=CAL_ABS_MAX)
{
gtk_show_error(WMain,"Too Small","Error!");
//设置调节按钮值为零
gtk_spin_button_set_value(SAns,0);
}
}
 
G_MODULE_EXPORT void on_WMain_destroy(GtkObject* widget, gpointer user_data)
{
gtk_main_quit();
}
 
GtkBuilder* gtk_load_glade(gchar* filename)
{
GtkBuilder *gb;
 
gb=gtk_builder_new();
if(!gtk_builder_add_from_file(gb,filename,NULL))return NULL;
gtk_builder_connect_signals(gb,NULL);
 
return gb;
}
 
void cal_get_widgets(GtkBuilder* gb)
{
w_(gb,WINDOW,WMain);
w_(gb,SPIN_BUTTON,SAns);
}
 
void cal_widget_init()
{
//初始化,设置调节按钮取值范围,数值超出此范围时自动调整为边界值。
gtk_spin_button_set_range(SAns,-CAL_ABS_MAX,CAL_ABS_MAX);
 
gtk_widget_show_all(GTK_WIDGET(WMain));
}
 
int main(int argc, char *argv[])
{
GtkBuilder *gb;
 
gtk_init(&argc,&argv);
 
gb=gtk_load_glade("gtk-cal.glade");
if(gb==NULL)return -1;
cal_get_widgets(gb);
cal_widget_init();
 
gtk_main();
 
return 0;
}

在以后的内容中,这个计算器将被逐渐完善。

访问多行文本

多行文本的使用比较复杂,涉及几个其他对象的使用。一个多行文本的内容储存在一个缓冲区GtkTextBuffer中,这个缓冲区需要用迭代器GtkTextIter访问、用GtkTextMark标记,文字样式用GtkTextTag设置。

看起来真的有些复杂。不过最基本的应用还是读、写。下面给出三个函数,可以直接读写多行文本。这几个函数基本够用了。

//读取多行文本中的文字内容
gchar* gtk_text_view_get(GtkTextView *text_view)
{
GtkTextBuffer *tb;
GtkTextIter st,stp;
 
tb=gtk_text_view_get_buffer(text_view); //获取对应的GtkTextBuffer
gtk_text_buffer_get_start_iter(tb,&st); //获得起始点
gtk_text_buffer_get_end_iter(tb,&stp); //获得结束点
return gtk_text_buffer_get_text(tb,&st,&stp,FALSE); //获得两点间所有字符
}
//在多行文本末尾追加文字,文字样式包含在text_tag中,如果不需要指定样式,text_tag设为NULL
void gtk_text_view_append_with_tag(GtkTextView* text_view, const gchar* text, GtkTextTag* text_tag)
{
GtkTextBuffer *tb;
GtkTextIter stp;
 
tb=gtk_text_view_get_buffer(text_view);
gtk_text_buffer_get_end_iter(tb,&stp);
gtk_text_buffer_insert_with_tags(tb,&stp,text,strlen(text),text_tag,NULL); //在结束点处追加字符
gtk_text_buffer_get_end_iter(tb,&stp);
gtk_text_view_scroll_to_iter(text_view,&stp,0,FALSE,0,0); //将光标置于结束点
}
//清空多行文本
void gtk_text_view_clear(GtkTextView *text_view)
{
gtk_text_buffer_set_text(gtk_text_view_get_buffer(text_view),"",0); //设置文本内容为空
}

此外,样式可以这样新建:

gtk_text_buffer_create_tag(gtk_text_view_get_buffer(text_view), tag_name, property1, value1, property2, value2, ... , NULL);

text_view是多行文本名字;tag_name是一个字符串,值不能和别的样式相同;property1,2,3,…各属性名字(字符串形式),可用的属性参见http://library.gnome.org/devel/gtk/unstable/GtkTextTag.html中的Property栏;value1,2,3,…各属性对应的值(字符串形式)。

如果以上的方法不够用,只好查参考了。

小提醒:多行文本一般都需要放在滚动区(GtkScrolledWindow)里面。

处理UTF-8字符串

要注意的问题是,GTK+内部使用UTF-8编码。在处理非ASCII编码的字符串时,切不可使用C语言string.h里的函数。在UTF-8中,字符含义比较复杂。还好,GLib中提供了很多用于处理多种编码字符串的函数,下面介绍一些用于处理UTF-8字符串的函数。

在http://library.gnome.org/devel/glib/stable/glib-Unicode-Manipulation.html中介绍了很多有关UTF-8字符串的实用函数。这些函数命名与string.h里的常用函数相近,只是多了前缀g_utf8_,表示是专门用来处理UTF-8字符串的。介绍几个吧。

  • g_utf8_strlen():统计UTF-8字符串中的字符数。在UTF-8编码中,不同语言的字符所占用的字节数不同(例如一个中文字符占3个字节),因而UTF-8所包含的字符数小于等于它的字节数,并且没有一个固定的关系。这个函数还是很常用且重要的。
  • g_utf8_find_prev_char():已知某个字符的首地址,查找它前一个字符的首地址。因为不同语言的字符所占用的字节数不同,两个紧邻字符地址之差可能大于1。
  • g_utf8_find_next_char():已知某个字符的首地址,查找它后一个字符的首地址。
  • g_utf8_strncpy():拷贝出字符串的前n个字符(而不是前n个字节)。
  • g_utf8_strchr():找到一个给定的字符最左端出现的位置。UTF-8字符串中字符是gunichar型,相当于一个32位无符号整数,对于非ASCII字符,其值大于127。
  • g_utf8_collate():比较两个字符串的大小(以字典序靠前的为小)。这个函数的强大之处在于,它可以根据所处的语言环境来判断两个字符串的字典顺序,可以比较任何语言的UTF-8字符串!

在http://library.gnome.org/devel/glib/stable/glib-String-Utility-Functions.html列出了一些跨字符集的实用函数,适用于任何字符集。其中有一部分常常能用上,比如g_snprintf()和g_strdup_printf(),它们的功能与C语言sprintf类似,都是把一串格式输出写进字符串里(常用于数字和字符混合输出到字符串里),但g_snprintf()和g_strdup_printf()更安全。g_snprintf()需要指定目的字符串长度,避免输出越界;g_strdup_printf()则在函数内部自行申请足够的空间存放目的字符串(注意它返回的字符串废弃之后需要用g_free()释放空间)。

在http://library.gnome.org/devel/glib/stable/glib-Character-Set-Conversion.html有一些字符集转换的函数,有些需要字符集转换的场合会用得上(比如文件名可能不是UTF-8编码,有时需要转换)。

原创粉丝点击