10.5.4 用GTK+开发图形界面程序
从C/C++到Java,c#,通过封装,GTK+可以支持多种语言的开发。在本节只学习利用C进行GTK+的开发。进行GTK+开发的前提是需要具备基本的C语言知识,了解基本的C语言语法,最好具备在Linux下进行C语言开发的经验。
进行图形界面的开发需要解决的基本问题就是如何使用图形界面元素和如何将界面元素与事件对应起来。GTK+中的界面元素可以分为两大类:
●可见的界面元素:包括窗口、按钮、菜单等。
●不可见的布局元素:包括box,table等,它们以特定的布局放置可见元素或者布局元素。
无论是哪种界面元素,都可以用GtkWidget的变量来引用。GTK+中的事件处理程序是通过回调函数(Callback Function)实现的,可以把回调函数理解为指向函数的指针。在程序中,函数的函数名就是一个回调函数的实例。
(1)基本的GTK+程序
下面从一个最基本的简单GTK+程序开始,逐步介绍GTK+程序的开发。假设要设计一个如图10-4所示的程序。该程序是一个图形界面程序,仅由一个窗口和一个按钮组成。用鼠标点击按钮时,终端会打印出“Hello,Welcome to HNCST!”的字符串;鼠标点击窗口的关闭按钮时,终端打印“Window Closed”字符串然后退出。由于程序运行时的外观与桌面系统所采用的外观主题相关,所以程序运行时的界面和本书中的图可能存在差异。
图10-4
由于程序功能简单,因此将所有代码都写在一个C代码文件中,假设代码文件名为hello.c,存放在当前的工作目录下,程序清单如下所示:
下面结合代码对GTK+程序的基本结构进行介绍,上述代码可以分为3部分。
第1行:程序预处理语句部分。
第2行~第8行:函数定义部分。
第9行~第26行:主程序部分。
第1行(预处理部分)利用include语句将<gtk/gtk.h>的头文件包含进来。这个头文件是开发GTK+程序时必须的头文件,GTK+库中的大部分接口、数据结构都在这个头文件中定义。通常只需包含这一个头文件,但在有些情况下还要使用一些额外的头文件。需要其他头文件通常是因为使用了GTK+中的非图形界面功能。
第2部分定义了两个函数。这两个函数作为界面元素的事件处理函数。同样是作为事件处理函数,事件处理函数的类型是由事件决定的,不同的事件对应的事件处理函数的原型也会不同。定义一个事件处理函数,要依照函数要关联的事件来定义。对于本例来说,按钮的“clicked”(点击)事件需要两个参数(GtkWidget*,gpointer),并且返回值为void,而窗口的“delete_event”(关闭)事件却需要三个参数(GtkWidget*,GdkEvent*和gpointer),并且返回值为void。具体每个事件需要什么类型的事件处理函数,可以参考GTK+的参考手册。
在本例中,第1个函数用来处理按钮被点击的事件。利用g_print函数在控制台上打印一个字符串,提示用户按钮被点击。第2个函数用来处理窗口被关闭的事件,打印一行提示后,退出程序。
第3部分的main函数是程序的主体。在main函数中依次完成初始化GTK+运行环境、创建界面元素、关联事件处理函数以及启动消息循环的工作,体现了GTK+程序的基本框架。
①初始化运行环境。程序的第12行设置GTK+的本地化信息,第13行利用函数gtk_init接收从启动程序中传递过来的参数信息,对GTK+进行其他信息的初始化。采用这种方式可以达到利用启动参数灵活设置GTK+程序运行状态的效果。
②创建界面元素并关联事件处理函数。程序的第10、11行定义了两个界面元素的指针变量,分别对应界面窗口和窗口中的按钮。由于GTK+采用类似面向对象中的继承机制,各种界面元素都采用单一的一种类型(GtkWidget)来引用。第14行建立一个顶层的窗口,即应用程序的主窗口,使用window变量存储指向主窗口的指针。第15行利用字符串设置window指向的主窗口的标题。第16行设置主窗口的边缘宽度为10。第17行将window产生的deleteevent事件和on_delete函数相关联。类似的,第19行创建一个标题为Hello,Welcome to HNCST!的按钮,第20行将按钮的clicked事件和on_btn_clicked函数关联起来。第22行将按钮放置在主窗口上,第23行显示主窗口上所有的界面元素。
根据GTK+的命名约定,如果要创建一个界面元素,通常可以采用以下形式:
●Gtk_类型名_new(参数),(见第14行)。
●Gtk_类型名_new_with_属性名(参数)(见第19行)。
设置某个元素属性时又可以采用“tk_类型名_set_属性(参数)”(见第15,16行)的方式。
类似的,如果要查询某个元素的属性时可以采用“gtk_类型名_get_属性(参数)”方式。
g_signal_connect方法是用来关联事件和事件处理函数的。严格地说,g_signal_connect并不是一个函数,而是一个宏,它的定义是对函数g_signal_connect_data的调用:
#define g_signal_connect(instance,detailed_signal,C_handler,data)→
g_signal_connect_data((instance),(detailed_signal),(c_handler),→
(data),NULL,(GConnectFlags) 0)
其中,反斜杠“→”表示续行。宏是预处理语句,它经过预处理,被展开为一个对函数g_signal_connectdata的调用。但在实际使用时,完全可以把它看作一个普通函数来使用,这也许是GTK+小组有意把这个宏命名得像一个函数的原因在C语言中,宏一般用大写的字符串来命名)。
定义中的参数说明如下:
●Instance是事件的产生者。
●Detail_signal是产生的事件。
●Chandler是处理事件的函数指针。
●Data是传递给事件处理函数的参数。
返回值是系统分配给事件处理函数的一个标识。
函数g_signal_connect_data需要6个参数,前4个参数与宏g_signal_connect的参数相同,最后两个参数分别为对数据进行包装处理的函数以及事件关联标志位(GconnectFlags)的组合。宏g_signal_connect要求最后两个参数为NUL以没有对数据进行包装处理的函数) 和0(不设置事件关联标志位)。
另外,由于GTK+只是模拟了一个界面元素的继承层次结构、因此为了更安全地完成基类型向派生类型的转化,GTK+广泛地应用宏来解决这个问题。例如,在程序清单第15行,方法gtk_window_set_title需要的第1个参数应该是一个GtkWindow类型的指针,而window被定义为一个GtkWidget类型的指针,因此使用宏GTK_WINDOW来进行转换。在GTK+的程序中,大量地运用了类似的宏。宏的格式和第15行的代码类似。如果需要将一个GtkWidget类型指针转化为GtkType类型的指针,需要使用的宏就是GTK_TYPE。
③启动消息循环。第24行利用函数gtk_main启动GTK+程序的消息循环,这样才能使图形界面程序真正运行起来。消息循环接收各种信号事件,并将这些信号转交给与之相关联的事件处理函数去处理。消息循环的退出通常意味着程序的结束,可以采用函数gtk_main_quit来退出消息循环。在本例中,当程序接收到事件delete_event时,事件处理函数on_delete调用gtk_main_quit函数来结束消息循环,进而退出程序。
主程序体现出设计GTK+程序的基本框架。对于大多数应用来说,main函数中需要改写的部分主要集中在程序清单的第14-22行。根据不同的要求,可以在这段代码中建立并设置不同的界面元素,关联相应的事件处理程序。
(2)编译GTK+源程序
GTK+程序也可以使用GCC命令来进行编译。由于GTK+用到的一些头文件、函数库没有安装在GCC默认的搜索路径内,因此,编译时需要额外增加一些参数向GCC指明这些文件的搜索路径。对于本例可以采用下面的命令来编译:
$ gcc hello.c-o hello`pkg-config--cflags--libs gtk+-2.0`
$./ hello
命令的后半部分是一个用一对反向单引号“`”引用的命令。命令pkg-config的作用是查询系统中安装的库的信息。此处该命令的作用是查询已安装的GTK+-2.0软件包的配置情况,并将其中有关预编译和编译(--cflags)的信息以及有关函数库(--libs)的信息输出出来。一对反向单引号(“、”)的作用是将命令的输出作为一个字符串看待,成为GCC的一部分命令选项。
单独运行一下“`”中的命令,检查一下它的输出结果,可以得到如下所示的输出:
hncst@ hncst-linux:~$ pkg-config gtk+-2.0--cflags--libs
-pthread-I/usr/include/gtk-2.0-I/usr/lib/gtk-2.0/include-I/usr/include/atk-1.0-I/usr/include/cairo-I/usr/include/gdk-pixbuf-2.0-I/usr/include/pango-1.0-I/ usr/include/gio-unix-2.0/-I/usr/include/glib-2.0-I/usr/lib/glib-2.0/include-I/usr/ include/pixman-1-I/usr/include/freetype2-I/usr/include/libpng12-pthread-lgtk-x11-2.0-lgdk-x11-2.0-latk-1.0-lgio-2.0-lpangoft2-1.0-lpangocairo-1.0-lgdk_pixbuf-2.0-lm-lcairo-lpng12-lpango-1.0-lfreetype-lfontconfig-gobject-2.0-lgmodule-2.0-lgthread-2.0-lrt-lglib-2.0
hncst@ hncst-linux:~$
运行命令后得到的关于GTK+的配置信息是一个格式化的字符串。字符串中提供了GCC命令的-I、-W、-1、-L等命令选项。
编译成功后,当前目录下会增加一个具有可执行权限的hello文件,通过键入./hello可以启动GTK+程序,看到类似图10-4所示的图形界面。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。