本部分内容:
- Glib基本概念
- 信号系统
- GTK+术语
- Hello world程序如何结束自己
- Gobject接口
- 增加菜单和布局
- Hildon 构件
- 使用附件
- 处理动态内存
- 避免使用废弃不用的函数
Glib基本概念
在Maemo中,所有的GTK程序都使用Glib工具库。这个工具库提供一组可移植的类型,这些类型可以为用C语言写的程序提供一定的可移植性。便利的工具函数和可移植的数据类型可以很容易写出具有移植性的软件。
从现在开始,我们将会用Glib类型,而不用C标准的类型了:
gboolean Either TRUE or FALSE. FALSE is equal to zero
gint8 8-bit signed integer
gint16 16-bit signed integer
gint32 32-bit signed integer
gint64 64-bit signed integer (there are no >64-bit ones)
gpointer Untyped pointer ('void *') (32/64-bit)
gconstpointer R/O untyped pointer('const void *') (32/64-bit)
gchar Compiler's 'char' (8-bit in gcc)
guchar Compiler's 'unsigned char'
gshort Compiler's 'short' (16-bit in gcc)
gushort Compiler's 'unsigned short'
gint Compiler's 'int' (32-bit normally in gcc)
guint Compiler's 'unsigned int'
glong Compiler's 'long' (32/64-bit in gcc)
gulong Compiler's 'unsigned long' (32/64-bit in gcc)
gfloat Compiler's 'float' (32-bits in gcc)
gdouble Compiler's 'double'(64/80/81-bits in gcc)
[ Glib 类型的名字及其含义]
所有符号整型以2S方式存储。对于每一个符号整型都有一个对应的无符号整型。
你应该试着坚持使用这些Glib类型,一般情况下你可以不必计较类型的大小。当然,也有例外:当你想优化内存时,或者数据来自于外部的数据(比如,原始位图数据,网络协议,硬件编程等等)。
GLib 也提供一些限制上述类型最大值的宏、字节序和字节序修改宏函数,在写可移植程序时,这些宏是非常有用的。在Glib API 文档中有详细的描述,可以参考如下:
http://maemo.org/api_refs/4.0/glib/index.html.
下面,我们将会使用少量函数写一个能跑的程序,同时,随着时间的推移,你将会欣赏用Glib写的代码(也有一些人放弃了Glib,因为Glib作为一个工具库实在太大、太多了)。由于Glib是共享库,所有Nokia的Internet Tablet 通常只有一个GUI程序在运行,所以Glib一般情况下不会耗费多少内存。
除了数据类型外,Glib同时也提供了如下的比较有用的函数集:
- 内存分配
- 消息输出、调试和日志函数
- 字符串处理 (UTF-8 and UCS-4)
- 日期和时间处理以及计数定时器
- 数据结构:
- 动态字符串
- 双向链表 (单向和双向)
- Hash 表
- 动态数组(也提供指针数组)
- 二叉树和N叉树
- 数据缓冲支持
- 其它一些功能
正如前面提到的,Glib的API可以在线浏览: http://maemo.org/api_refs/4.0/glib/index.html. 对于Maemo中使用的其他的库函数的参考,你可以到这里找找看: http://maemo.org/development/documentation/apis/4-x/.
如果在你的开发系统上已经安装了合适的文档包,你也应当试试 devhelp,这是一个非常好的程序,可以让你浏览GNOME库文档,并且提供超文本和search功能。

信号机制
为了处理不同组件之间交互,不同的库有不同的方法去实现事件和变化时的通知机制。在设计和限制方面各有千秋。在GTK中使用的设计模型是注册/自动激发回调函数的这么一个机制。这种机制称之为Gsignal, 在Gobject库中实现的。Gobject是一个框架或者架构,使用它你可以用C语言编写出面向对象的结构,就像Java和C++那样。Gobject并不需要特殊的工具函数,因此它的可移植性非常好,当然,Gobject中使用了大量的Glib数据结构。
关于如何使用Gobject(实现自己的类、扩展已有的类,等等)这里并不准备介绍,因为这是个比较复杂的问题,而且在开始用gtk+编程时也没有必要非要把Gobject搞的很透。呵呵。
GTK+ widget使用GSignal机制去实现通知:当有什么事情发生时。然后这些消息就传递给那些关心这些事件的监听者(通过回调函数的形式)。在GTK+中,并没有所谓的共享事件总线,但是你可以发挥想象:在widget和回调函数之间是建立了“链接”的。GSignal还支持优先级的处理。
每一个类可以定义其型号类型,而类的实例可以发射这些信号。Signal是通过一个文本字符串和一个信号源标示的。
我们链接一个信号:指定一个具备发射信号的对象并且指定信号的名称。你可以把名字认为是类型,实际上它仅仅是用于区分不同的信号,比如“clicked”和“selected” 。我们链接的对象是谁?就是用C语言写的回调函数。请注意:发射信号的对象并不直接调用回调函数,而是使用GObject提供的普遍的信号发送框架。这个框架使得发射者和接收者仅仅提供相同的API就可以了。
假设在面向对象编程成熟之前就设计了C语言,那么,GObject和signal看起来就顺眼多了。如果你仅仅使用过面向对象语言编程,GObject对你来说,看起来就比较奇怪了。习惯了就好了。
你可以通过阅读API或者很多与GObject相关的数据去熟悉它,推荐一本书:【The Official Gnome 2 Developer’s Guide】。直接从代码中理清GObject的架构并不是一个好的主意,因为代码比较复杂。不过你早晚要熟悉GObject的代码的。J
GTK+ 术语
在开始GTK+之前,我们需要看看有哪些术语:
- Widget: 能在屏幕显示并且允许用户和它交互的这么一个控件。比如:scrollbar,Button,Menu,等等。
- Container: 一个特殊的容器控件,能够给其它的一些控件提供容身之所,并且把那些控件以一定的方式组织在一块,显示在屏幕上。另外容器可以套容器,就是大鱼吃小鱼,小鱼吃虾米。比如: Window, VBox, HBox, Toolbar.
- Packing: 填充,这是一个动作。就是把一个widget放到一个容器控件中,这么一个动作就叫做填充。一般情况下,我们这样讲:把一个widget填充到一个容器中。填充这个动作将会做些空间分配和布局方面的工作。如果一个widget暂时不可见,这个填充动作暂时是不做的。
- Child Widget: 子控件,就是被填充到一个容器中的控件.反过来讲,一个控件的父控件就是其容器。一个控件不能有多个父控件。
- Widget Tree: 所有的控件和其容器都是一个root控件的子控件。对于每一个window都有一个widget tree。
- Event: 事件,就是进程外发生什么事情后给出的通知。这些通知一般来自于HID-sysem,并且由GTK+转为信号。信号处理机制就是处理这些事件的。
- Visibility:每一个widget都可以设置可见或者不可见。只有父控件(容器)可见,才能在屏幕上看到图像。为了让widget tree中的每一个控件可见,我们需要告诉这些控件,显示与否。通常我们在创建完widget tree后,统一处理这种告知的事情。
- Property: 属性,这实际是和Gobject相关的东西,不过在GTK+中一样得到了应用。一般来讲,property就是可以设置/取得的具有名字的数据或者值。当我们设置属性时,对象会执行一些操作来反映值的变化。读取一个属性也会触发一些代码执行。
Hello World 示例程序如何结束自己呢?
/**
* gtk_helloworld-2.c
*
* This maemo code example is licensed under a MIT-style license,
* that can be found in the file called "License" in the same
* directory as this file.
* Copyright (c) 2007 Nokia Corporation. All rights reserved.
*
* This version adds proper mechanisms to end the program.
*
* Look for lines with "NEW" or "MODIFIED" in them.
*/
#include <stdlib.h>
#include <gtk/gtk.h>
/**
* NEW
*
* Callback function (event handler) for the "delete" event.
* This event is emitted by GTK+ main loop after a window manager has