📄 gtk_tut-2.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Draft//EN"><HTML><HEAD><meta http-equiv="pragma" content="no-cache"><TITLE>GTK入门导引: 开始</TITLE></HEAD><BODY><A HREF="gtk_tut-1.html" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-1.html"><IMG SRC="prev.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/prev.gif" ALT="Previous"></A><A HREF="gtk_tut-3.html" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-3.html"><IMG SRC="next.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/next.gif" ALT="Next"></A><A HREF="gtk_tut.html#toc2" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut.html#toc2"><IMG SRC="toc.gif" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/toc.gif" ALT="Contents"></A><HR><H2><A NAME="s2">2. 开始</A></H2><P>第一件要做的是当然是取得一份GTK的原始码并且安装进您的系统中.您可以从GIMP取得一份发行版, 或者是从Peter Mattis's的"家中"ftp.xcf.berkely.edu/pub/pmattis(however, it has been changed to ftp.gimp.org)取得一份. GTK使用GNU的autoconf来设定.一但您解开档案, 输入configure --help来看看选项表列.<P>在介绍GTK的一开始, 我们尽可能挑最简单的程式.这个程式将会产生200x200点的视窗, 而且没办法离开, 除非从shell中将它杀掉. <P><BLOCKQUOTE><CODE><PRE>#include <gtk/gtk.h>int main (int argc, char *argv[]){ GtkWidget *window; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_show (window); gtk_main (); return 0;}</PRE></CODE></BLOCKQUOTE><P>所有程式理所当然一定会包含gtk/gtk.h, 其中宣告了所有变数, 函数, 及资料及结构.这些东西您会在您的GTK应用软体中用到.<P>下一行<P><BLOCKQUOTE><CODE><PRE>gtk_init (&argc, &argv);</PRE></CODE></BLOCKQUOTE><P>呼叫函数gtk_init(gint *argc, gchar ***argv)将会启动GTK.该函数设定了一些内定的值, 并且後续交给gdk_init(gint *argc, gchar ***argv)继续处理. 该函数启动了一些函数库以供使用, 设定了内定的信号处理,检查传给您的程式的命令列参数.看看以下:<P><UL><LI> <CODE>--display</CODE></LI><LI> <CODE>--debug-level</CODE></LI><LI> <CODE>--no-xshm</CODE></LI><LI> <CODE>--sync</CODE></LI><LI> <CODE>--show-events</CODE></LI><LI> <CODE>--no-show-events</CODE></LI></UL><P>这些参数将会从参数表中删去, 所剩下的会传给您做後续的处理.这样会产生标准的参数表(除了GTK所使用的)以供您使用.<P>下面这两行程式会产生并显示一个视窗.<P><BLOCKQUOTE><CODE><PRE> window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_widget_show (window);</PRE></CODE></BLOCKQUOTE><P>GTK_WINDOW_TOPLEVEL参数指定了我们承习视窗管理程式的外观.即便我们产生一个0x0大小的视窗, 没有子视窗的视窗内定被设为200x200,如此我们依然可以处理它.<P>gtk_widget_show()函数, 让GTK知道,我们已经处理完设定其属性的工作, 并且可以显示它.<P>最後一行进入GTK的主要处理回圈.<P><BLOCKQUOTE><CODE><PRE>gtk_main ();</PRE></CODE></BLOCKQUOTE><P>gtk_main()是个在每个GTK应用软体中都会看到的一个函数.当控制到达这里, GTK会"睡"一下来等待X事件的发生(诸如像按键被按下).在我们最简单的例子里面, 事件会被忽略掉. 因为我们没有处理它.<P><P><H2><A NAME="ss2.1">2.1 用GTK来写Hello World</A></H2><P>好, 现在我们来写一个有一个视窗物件的视窗(一个按钮). 这是个GTK的标准hello world. 这会建立起一个新的GTK软体的良好基础.<P><BLOCKQUOTE><CODE><PRE>#include <gtk/gtk.h>/* 这是个callback函数. 其资料参数在本例中被忽略 * 以下有更多的callback函数. */void hello (GtkWidget *widget, gpointer *data){ g_print ("Hello World\n");}/* another callback */void destroy (GtkWidget *widget, gpointer *data){ gtk_main_quit ();}int main (int argc, char *argv[]){ /* GtkWidget用以储存视窗物件形态 */ GtkWidget *window; GtkWidget *button; /* 这在所有GTK应用软体中用到. 参数由命令列中解译出来并且送到该应用软体中. */ gtk_init (&argc, &argv); /* 产生新视窗 */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* 当视窗收到"destroy"信号时(可由该软体或视窗管理程式所送出) 所会被呼叫到的destroy函数一如以下所定义的一般. 送到该函数的资料将会是NULL,并且在该函数中被忽略 */ gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (destroy), NULL); /* 设定视窗的边框的宽度 */ gtk_container_border_width (GTK_CONTAINER (window), 10); /* 产生一个新的按钮并带有"Hello World"的字在上面. */ button = gtk_button_new_with_label ("Hello World"); /* 当该按键收到"clicked"信号, 它会呼叫hello()这个函数. 并且以NULL做为其参数. hello()函数在以上已定义过. */ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (hello), NULL); /* 这会导致当"clicked"这个按钮被按下的时候, 呼叫gtk_widget_destroy(window)而使该视窗被关闭 当然了, 关闭的信号会从此处或视窗管理程式所送来 */ gtk_signal_connect_object (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), GTK_OBJECT (window)); /* 这个动作会把这个按钮结合到该视窗(a gtk container). */ gtk_container_add (GTK_CONTAINER (window), button); /* 最後一步是显示最新产生的视窗物件... */ gtk_widget_show (button); /* 及该视窗 */ gtk_widget_show (window); /* 所有GTK程式都一定要有gtk_main(). 所有控制结束於此并等带事件的发生 (像按下一键或滑鼠的移动). */ gtk_main (); return 0;}</PRE></CODE></BLOCKQUOTE><P><H2><A NAME="ss2.2">2.2 编译Hello World</A></H2><P>用以下命令来编译:<P><BLOCKQUOTE><CODE><PRE>gcc -Wall -g helloworld.c -o hello_world -L/usr/X11R6/lib \ -lglib -lgdk -lgtk -lX11 -lXext -lm</PRE></CODE></BLOCKQUOTE><P>函数库必须在内定的搜寻路径内, 如果找不到, -L<library directory> 则gcc会去找这些目录,看看所需要的函数库是否找得到.例如, 在我的Debian Linux系统中, 我已经增加了<CODE>-L/usr/X11R6/lib</CODE>用来寻找X11函数库.<P>以下函数库是很重要的. linker在处理之前, 必须知道什麽函数要用那一个函数库.<P>函数库如下:<UL><LI>glib函数库(-lglib), 包含一些有用的函数, 这个例子中只用到g_print(),因为GTK是建在glib之上, 所以您几乎都一定会用到它.详见<A HREF="gtk_tut-17.html#sec_glib" tppabs="http://extend.hk.hi.cn/%7ehusuyu/http/beginner/gtk/gtk_tut-17.html#sec_glib">glib</A>一段. </LI><LI>GDK函数库(-lgdk), Xlib的包装程式.</LI><LI>GTK函数库(-lgtk), 视窗物件函数库, 基於GDK之上.</LI><LI>xlib函数库(-lXlib) 基本上为GDK所用.</LI><LI>Xext函数库(-lXext). 包含了shared memory pixmaps及其它的一些X extensions.</LI><LI>math函数库(-lm). 为GTK所用, 有多方面用途.</LI></UL><P><H2><A NAME="ss2.3">2.3 Signals及Callbacks的原理</A></H2><P>在我们更进一步探讨hello world之前,我们要讲一下事件(events)及回呼函数(callbacks).GTK本身是个事件驱动的工具, 这意味著它会在gtk_main进入停歇状态,一直到一个事件发生, 并且将控制交给适当的函数来处理.<P>控制权的交出是由"signals"来决定的.当事件发生, 诸如按下滑鼠的一个按键, 对应的信号会由该视窗物件所送出.这便是GTK的主要工作. 要使一个按下的动作执行一个命令,我们设定一个信号处理函数来撷取这个信号, 并且呼叫适当的函数.这工作是由像以下的函数来完成的:<P><BLOCKQUOTE><CODE><PRE>gint gtk_signal_connect (GtkObject *object, gchar *name, GtkSignalFunc func, gpointer func_data);</PRE></CODE></BLOCKQUOTE><P>其第一个参数是会送出信号的物件,第二个是希望接取的信号名称.第三个是当信号送出时的接取函数, 第四个则是要送给该函数的资料.<P>第三个参数被称为"callback function", 而且必需是以下的形式:<P><BLOCKQUOTE><CODE><PRE>void callback_func(GtkWidget *widget, gpointer *callback_data);</PRE></CODE></BLOCKQUOTE><P>第一个参数是指向该物件的指标,第二个是在gtk_signal_connect()的最後一个参数.<P>另外一个在hello world中有用到的函数是:<P><BLOCKQUOTE><CODE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -