GTK入门导引
来源:Linux-cn.com
作者:Webmaster
时间:2007-05-05
点击:
[ 收藏] [ 投稿]
|
20. 写出属於您自己的物件
20.1 概说
虽然GTK的物件基本上是够用了, 但有时您还是需要产生自己所需要的物件型态. 如果已经有一个既存的物件很接近您的需求, 那麽您可以把程式改个几行就可以达到您的需求了. 但在您决定要写一个新的物件之前, 先确认是否有人已经写过了. 这会避免重复浪费资源, 并保持物件数量达到最少, 这会使程式及介面比较统一一点. 另一方面, 一旦您写好您的物件, 要向全世界公告, 这样其它人才会受益. 最好的公告地点大概就是gtk-list了.
20.2 物件的解析
为了要产生一个新的物件, 了解GTK的运作是很重要的. 这里只简单的说一下. 详细请参照reference documentation.
GTK物件是以流行的物件导件的观念来设计的. 不过, 依然是以C来写的. 比起用C++来说, 这可以大大改善可移植性及稳定性. 但同时, 这也意味著widget writer需要小心许多实作上的问题. 所有同一类别的物件的一般资讯 (例如所有的按钮物件)是放在 class structure. 只有一份这样的结构. 在这份结构中储存类别信号的资讯. 要支撑这样的继承, 第一栏的资料结构必须是其父类别的资料结构. 例如GtkButton的类别宣告看起来像这样:
struct _GtkButtonClass
{
GtkContainerClass parent_class;
void (* pressed)(GtkButton *button);
void (* released) (GtkButton *button);
void (* clicked)(GtkButton *button);
void (* enter)(GtkButton *button);
void (* leave)(GtkButton *button);
};
|
当一个按钮被看成是个container时(例如, 当它被缩放时), 其类别结构可被传到GtkContainerClass, 而其相关的栏位被用来处理信号.
对每个物件结构来说, 都有一些状况上的不同. 该结构都有一些资讯是不太一样的. 我们称此结构为object structure. 如按钮一类, 看起来像这样:
struct _GtkButton
{
GtkContainer container;
GtkWidget *child;
guint in_button : 1;
guint button_down : 1;
};
|
可以看到, 第一栏是其父类别的物件资料结构, 因此该结构可以传到其父类别的物件结构来处理.
20.3 产生一个组合物件
标头档
每个物件类别都有一个标头档来宣告其物件, 类别结构及其函数. 有些特性是值得指出的. 要避免重复宣告, 我们将整个标头档包成:
#ifndef __TICTACTOE_H__
#define __TICTACTOE_H__
.
.
.
#endif /* __TICTACTOE_H__ */
而且加入让C++程式不会抓狂的定义码:
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
.
.
.
#ifdef __cplusplus
}
#endif /* __cplusplus */
|
除了函数及结构外, 我们宣告了三个标准巨集在标头档中 TICTACTOE(obj), TICTACTOE_CLASS(klass), 及IS_TICTACTOE(obj), 当我们传入一个指标到物件或类别结构中, 它会检查是否是我们的tictactoe物件.
这里是完整的标头档:
#ifndef __TICTACTOE_H__
#define __TICTACTOE_H__
#include <gdk/gdk.h>
#include <gtk/gtkvbox.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define TICTACTOE(obj)GTK_CHECK_CAST (obj,
tictactoe_get_type (), Tictactoe)
#define TICTACTOE_CLASS(klass)GTK_CHECK_CLASS_CAST
(klass, tictactoe_get_type (), TictactoeClass)
#define IS_TICTACTOE(obj)GTK_CHECK_TYPE (obj,
tictactoe_get_type ())
typedef struct _TictactoeTictactoe;
typedef struct _TictactoeClassTictactoeClass;
struct _Tictactoe
{
GtkVBox vbox;
GtkWidget *buttons[3][3];
};
struct _TictactoeClass
{
GtkVBoxClass parent_class;
void (* tictactoe) (Tictactoe *ttt);
};
guinttictactoe_get_type(void);
GtkWidget* tictactoe_new (void);
voidtictactoe_clear(Tictactoe *ttt);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __TICTACTOE_H__ */
|
_get_type()函数.
我们现在来继续做我们的物件. 对每个物件来说, 都有一个重要的核心函数 WIDGETNAME_get_type(). 这个函数, 当第一次被呼叫的时候, 会告诉GTK有关该物件类别, 并取得一个ID来辨视其物件类别. 在其後的呼叫中, 它会返回该ID.
guint
tictactoe_get_type ()
{
static guint ttt_type = 0;
if (!ttt_type)
{
GtkTypeInfo ttt_info =
{
"Tictactoe",
sizeof (Tictactoe),
sizeof (TictactoeClass),
(GtkClassInitFunc) tictactoe_class_init,
(GtkObjectInitFunc) tictactoe_init,
(GtkArgFunc) NULL,
};
ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info);
}
return ttt_type;
}
|
GtkTypeInfo结构有以下定义:
struct _GtkTypeInfo
{
gchar *type_name;
guint object_size;
guint class_size;
GtkClassInitFunc class_init_func;
GtkObjectInitFunc object_init_func;
GtkArgFunc arg_func;
};
|
这资料结构自我解释的很好. 在此, 我们将会忽略掉arg_func这一栏: 它很重要, 可以允许用来给设定解译式语言来设定, 但大部份相关工作都还没有完成. 一旦GTK被正确的填入该资料结构, 它会知道如何产生某一个特别的物件类别.
如果您对本文有任何疑问或者建议,请到讨论区发表您的意见:
>>
论坛入口 <<
上一篇:GTK+/Gnome应用开发
下一篇:GTK v1.2 Tutorial(英文)
【文章评论】
【收藏本文】
【推荐好友】
【打印本文】
【我要投稿】 【论坛讨论】
更多相关文章
|