|

楼主 |
发表于 2003-7-5 17:33:23
|
显示全部楼层
后端编程: 回到Gtemp
第一次编译
如果没有保存,就在glade的主窗口保存你的程序。点联编按钮来生成程序代码。 如果你想的话,可以检查一下gtemp子目录看生成些什么。
打开一个终端窗口
在gtemp目录,输入autogen.sh
你可以看到一长列autogen和autoconf的信息。除非 配置突然跳出,否则不用管它。
当autogen结束输入'make'。
进入/src子目录。列文件可以看到已经有一个gtemp的可执行文件。
输入./gtemp运行这个可执行文件。
gtemp程序开始运行。可以看到我们创建的所有窗口--主程序窗口和"关于"对话框都打开了。你可以关闭"关于"窗口,象前面所讨论的那样它已经设好了信号和回调函数。不过,我们不希望一下子打开两个窗口,这是我们要修改的第一件事情。
点窗口右上角X关闭程序。注意命令行并没有返回到开始运行gtemp的终端窗口。这是 因为为窗口图标自动创建的回调函数(最小化、最大化和关闭)没有完全关闭程序。这 显示得很愚蠢,同时你在一个程序里使用多个窗口。用户关闭弹出窗口,程序应该结束。 我们将来设置回调函数以便点击X时程序关闭。这是我们要修改的第二件事情。
我们需要当按下"退出"按钮或选择菜单条"文件"下的退出时程序能够退出。这是加入 第三件事情。还要当选择"帮助"菜单下"关于"菜单项时弹出"关于"窗口。还剩最后一个 事情, C 到 F 或 F 到 C 的实际转换。
程序开始时只打开一个窗口
打开一个编辑窗口。本教程作者使用Gvim,不过Emacs、gedit或一个字处理软件也 可以。Gvim和Emacs很适合,因为能给代码加颜色。打开gtemp的main.c文件。它在 /src子目录下。
main.c文件开头几行说明了glade不会改写这个文件,可以根据需要来修改它。记住, 如果你打开的glade生成文件没有这样说,就不要编辑它。来到main()函数,找到声明 GtkWidget *gtemp_about,删掉它。
向下翻找到
gtemp_about = create_gtemp_about ();
gtk_widget_show (gtemp_about);
删掉它们。
Glade为每一个设计的窗口生成create_xxx()函数比如create_gtemp_about()。当需要时可以用在你的代码中来创建它们。每一个窗口创建后用with gtk_widget_show()来显示。 现在我们删掉了这些行,不过很快会把它们加入到"关于"菜单项的回调函数中。
使Gtemp主窗口右上角的X工作
首先,我们需要加入另一个回调函数。在Glade选择Gtemp程序窗口,进入属性窗口。 在signals页,选择GtkWidget信号下的delete_event信号,把这个信号句柄加入列表,保存,重建程序。
用你选择的编辑器打开callbacks.c文件。你可以看到前面我们加入的所有信号句柄或 回调函数,刚才加入的delete event在文件的最下面。转到这儿。
加入
gtk_main_quit();
return FALSE;
在on_gtemp_app_delete_event()函数里。 想知道gtk_main_quit()函数的更多信息,你可以查询 gtk+ API在 gtk-General部分.
使"退出"菜单项和"退出"按钮工作
在on_quit1_activate()函数加入
gtk_main_quit()
函数调用。就做这么多。 on_quit_button_clicked()函数也这样处理。
选择"关于"菜单项时载入"关于"窗口
查找函数名为on_about1_activate()在这儿加入从main.c文件删 掉的创建窗口的代码。把下面的代码加进去:
GtkWidget *about
about = create_gtemp_about();
gtk_widget_show(about);
这就可以了。
现在可以测试刚才所做的工作。在/src输入make重新编译。如果没有打字或其它错误, make不会显示任何错误信息。运行gtemp检查我们所做的工作。
现在我们开始编写后端。这个很简单,不过在一个复杂的程序里,可能有几个辅助的 文件,绝大多数后端不会放在callbacks.c,比如在gtemp里.
最后使Gtemp能够转换温度单位
目前在callbacks.c里应该有四个空的回调函数。其中两个on_properties1_activate() 和on_preferences1_activate(),现在用不到。使用剩下的 on_fahr_entry_activate()和on_cel_entry_activate()。
我们将要编写一个函数叫做compute_temp(),它将被这两个 entry_activate回调函数调用。定义两个标志, C_TO_F和F_TO_C以便我们知道正在进行哪种转换。 Compute_temp()以调用的控件、用户输入的温度和转换类型做为参数。
在文件头部,在其它#define下面加入这几行
#define C_TO_F 0
#define F_TO_C 1
void compute_temp(GtkWidget *this_widget, float temperature, int type);
这是这些函数和标志的声明。
在文件尾部,所有回调函数的下面,加入这个函数:
void compute_temp(GtkWidget *this_widget, float temperature, int type)
{
GtkWidget *other_entry = NULL;
float result = 0.0;
gchar *result_string = NULL;
switch(type) {
case C_TO_F:
result = ((9.0 / 5.0) * temperature) + 32.0;
other_entry = lookup_widget(this_widget, "fahr_entry");
break;
case F_TO_C:
result = (5.0 / 9.0) * (temperature - 32.0);
other_entry = lookup_widget(this_widget, "cel_entry");
break;
}
result_string = g_strdup_printf("%5.2f", result);
gtk_entry_set_text(GTK_ENTRY(other_entry), result_string);
g_free(result_string);
}
单步执行这个函数,它声明了正确的变量,进入了一个分支语句,在这个语句中温度单位的转换取决于传入了哪个文本框:other_entry = lookup_widget(this_widget, "cel_entry"); and other_entry = lookup_widget(this_widget, "fahr_entry"); 使用glade支持函数lookup_widget() 找到没有用户输入的那个文件框。Gtk_entry只接收文本,因此我们把浮点数通过 g_strdup_printf()转换成文本。这个功能很象printf() 函数,不管字符串有多长都能确保分配了足够的内存。接下来用gtk_entry_set_text() 把结果写入gtk_entry控件。用g_free()释放我们用 g_strdup_printf()创建的结果字符串。
所有的这些函数都可以在gnome.org上API部分查到。GtkEntry详细信息请看 这页。 你可以在这里 查到Glib字符串功能。
还需要在entry_activate里写入代码来实际运行compute_temp函数。找到回调函数名为 on_fahr_entry_activate() 加入以下代码:
gchar *fahr = NULL;
fahr = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
compute_temp(GTK_WIDGET(entry), atof(fahr), F_TO_C);
这儿我们没有做 任何错误检查,只是用atof()把字符串fahr转换成浮点数。后面我们会加入错误检查。找到on_cel_entry_activate()函数,加入以下代码:
gchar *celsius = NULL;
celsius = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
compute_temp(GTK_WIDGET(entry), atof(celsius), C_TO_F);
同样, 我们后面会加入错误检查。注意在每一个代码片断我们使用GtkEditable代替GtkEntry。这是因为GtkEntry某些方面不推荐使用(在Gtk+-1.0,不过在2.0中以恢复了entry_get_text 函数),特别是gtk_entry_get_text()函数。由于GtkEntry是GtkEditable的一个子类,用GtkEditable函数是比较有效的。我们只要记住用GTK_EDITABLE()转换宏把它 转换成一个新类。
现在,我们有一个可用的程序
重新编译看看。在/src子目录输入make,修改任何可能的打字错误,运行程序。 如果你在文本框只输入数字,它会运行得很好。试着在其中一个文本框里输入'abc'。 它给出了一个结果,因为atof()函数强行把"abc"转换成一个浮点数, 不过我们知道结果是错的。如果这个程序只是自己用,而且你知道输入什么才能得到 正确结果(象大多数编程者那样),那我们现在就停下来。不过让我们更进一小步,加入 简单的错误检查和提示。
加入错误提示
我们要写另一个函数check_temperature_value(),它将检查以确保输入的数值是数值型而不是其它。这个函数同样也被两个entry_activate函数调用,向程序 状态条输出一条错误信息。
在callbacks.c文件的底部加入函数:
gint check_temperature_value(GtkWidget *this_widget, gchar *value)
{
GtkWidget *appbar;
gint num = 0;
gchar this_char = '\0';
this_char = *value;
if (!this_char)
return 0;
while (this_char != '\0') {
if (!isdigit(this_char)) {
/* set up the error message */
appbar = lookup_widget(GTK_WIDGET(this_widget), "appbar1");
gnome_appbar_push(GNOME_APPBAR(appbar), " lease enter numbers only");
return 0;
} else {
num++;
this_char = value[num];
}
}
return 1;
}
我们需要在entry_activate回调函数调用这个函数。加入以下这些行到 on_cel_entry_activate()中,在compute_temp() 函数调用之前:
if (!check_temperature_value(GTK_WIDGET(entry), celsius))
return;
clear_appbar(GTK_WIDGET(entry));
把同样的行加入到 on_fahr_entry_activate()中,在 compute_temp()函数调用之前:
if (!check_temperature_value(GTK_WIDGET(entry), fahr))
return;
clear_appbar(GTK_WIDGET(entry));
最后我们需要clear_appbar()函数。它只是在输入是个正确的数字时从状态条上消除 错误信息。把它加入callbacks.c文件的最后:
void clear_appbar(GtkWidget *this_widget)
{
GtkWidget *appbar;
appbar = lookup_widget(GTK_WIDGET(this_widget), "appbar1");
gnome_appbar_clear_stack(GNOME_APPBAR(appbar));
}
不要忘了在文件头部附近加入两个函数头。编译程序,现有你有一个能工作、错误检查并发出信息的Gtemp版本! |
|