⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x2152.html

📁 GTK/Gnome 经典图书
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"><HTML><HEAD><TITLE>创建一个复合构件</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="GTK+ 2.0 教程"HREF="book1.html"><LINKREL="UP"TITLE="编写你自己的构件"HREF="c2132.html"><LINKREL="PREVIOUS"TITLE="一个构件的剖析"HREF="x2141.html"><LINKREL="NEXT"TITLE="从头创建构件"HREF="x2259.html"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">GTK+ 2.0 教程</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="x2141.html"ACCESSKEY="P">&#60;&#60;&#60; Previous</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">编写你自己的构件</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="x2259.html"ACCESSKEY="N">Next &#62;&#62;&#62;</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="SEC-CREATINGACOMPOSITEWIDGET">创建一个复合构件</H1><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN2154">介绍</H2><P>你可能乐于创建这样一种类型的构件,它仅仅是其它 GTK 构件的一个组合。为组装用户界面元素以重复使用提供了便利的方法。在标准发布中的文件选择和颜色选择构件就是这种类型构件的示例。</P><P>我们将要在这一节创建一个井字游戏构件,一个 3X3 的开关按钮矩阵,当同一列、同一行或是对角线的所有三个按钮都被按下时触发一个信号。</P><P><SPANCLASS="INLINEMEDIAOBJECT"><IMGSRC="images/tictactoe.png"></SPAN></P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN2162">选择一个父类</H2><P>通常,一个复合构件的父类是一个容纳复合构件的所有元素的容器类。例如,文件选择构件的父类就是对话框类。因为我们的按钮排列在一个表中,看起来应该让表类作为我们的父类。但不幸的是,这样无法工作。构件的创建分为两个函数 - 一个用户调用的 <TTCLASS="LITERAL">WIDGETNAME_new()</TT> 函数,另一个是 <TTCLASS="LITERAL">WIDGETNAME_init()</TT> 函数作基本的初始化构件的工作,它不使用传递给 <TTCLASS="LITERAL">_new()</TT> 函数的参数。子构件只调用父构件的 <TTCLASS="LITERAL">_init</TT> 函数。但是这个分工不能在表中正常工作,因为创建表时需要知道表的行数和列数。除非我们想重新实现 <TTCLASS="LITERAL">gtk_table_new()</TT> 的大多数功能,我们最好避免从表派生构件。由于这个原因,代替表,我们从纵向盒派生构件,然后把表放入纵向盒。</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN2170">头文件</H2><P>每个构件类有一个头文件,该头文件用于声明构件的对象、类结构和公共函数。有两个特性是值得指出的。为避免重复定义,我们把整个头文件放入如下语句里:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">#ifndef __TICTACTOE_H__#define __TICTACTOE_H__...#endif /* __TICTACTOE_H__ */</PRE></TD></TR></TABLE><P>并且让 C++ 程序也能包含该头文件:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">#ifdef __cplusplusextern "C" {#endif /* __cplusplus */...#ifdef __cplusplus}#endif /* __cplusplus */</PRE></TD></TR></TABLE><P>在我们的头文件里,和函数、结构一起声明的还有三个标准宏。 <TTCLASS="LITERAL">TICTACTOE(obj)</TT>, <TTCLASS="LITERAL">TICTACTOE_CLASS(class)</TT> 和 <TTCLASS="LITERAL">IS_TICTACTOE(obj)</TT>,这三个宏分别是将指针转换为指向对象、类的指针和检测一个对象是否是一个井字游戏构件。</P><P>下面是全部的头文件:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">&#13;/* GTK - GIMP工具包 * 版权 (C) 1995-1997 Peter Mattis, Spencer Kimball 和 Josh MacDonald 所有 * * 本程序是自由软件。你可以在自由软件基金发布的 GNU GPL 的条款下重新分发 * 或修改它。GPL 可以使用版本 2 或(由你选择)任何随后的版本。 * * 本程序分发的目的是它可能对其他人有用,但不提供任何的担保,包括隐含的 * 和适合特定用途的保证。请查阅GNU通用公共许可证获得详细的信息。 * * 你应该已经随该软件一起收到一份GNU通用公共许可。如果还没有,请写信给 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#ifndef __TICTACTOE_H__#define __TICTACTOE_H__#include &#60;gdk/gdk.h&#62;#include &#60;gtk/gtkvbox.h&#62;#ifdef __cplusplusextern "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 _Tictactoe       Tictactoe;typedef struct _TictactoeClass  TictactoeClass;struct _Tictactoe{  GtkVBox vbox;    GtkWidget *buttons[3][3];};struct _TictactoeClass{  GtkVBoxClass parent_class;  void (* tictactoe) (Tictactoe *ttt);};GtkType        tictactoe_get_type        (void);GtkWidget*     tictactoe_new             (void);void	       tictactoe_clear           (Tictactoe *ttt);#ifdef __cplusplus}#endif /* __cplusplus */#endif /* __TICTACTOE_H__ */&#13;</PRE></TD></TR></TABLE></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN2182"><TTCLASS="LITERAL">_get_type()</TT> 函数</H2><P>现在,我们继续实现我们的构件。<TTCLASS="LITERAL">WIDGETNAME_get_type()</TT> 函数是每个构件的核心函数。当第一次调用时,该函数告之 GTK 这个构件类并得到一个能唯一识别该构件类的 ID。之后的调用,只返回这个ID。</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">GtkTypetictactoe_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,	(GtkArgSetFunc) NULL,        (GtkArgGetFunc) NULL      };      ttt_type = gtk_type_unique (gtk_vbox_get_type (), &#38;ttt_info);    }  return ttt_type;}</PRE></TD></TR></TABLE><P>GtkTypeInfo 结构定义如下:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">struct _GtkTypeInfo{  gchar *type_name;  guint object_size;  guint class_size;  GtkClassInitFunc class_init_func;  GtkObjectInitFunc object_init_func;  GtkArgSetFunc arg_set_func;  GtkArgGetFunc arg_get_func;};</PRE></TD></TR></TABLE><P>这个结构的域很形象。我们在这里忽略 <TTCLASS="LITERAL">arg_set_func</TT> 和 <TTCLASS="LITERAL">arg_get_func</TT> 这两个域:它们很重要,但大部分还未实现,它们允许解释性语言方便地设置构件的属性。一旦 GTK 正确的填充了该结构,它就知道了如何去创建一个特殊构件类型的对象。</P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN2193"><TTCLASS="LITERAL">_class_init()</TT> 函数</H2><P><TTCLASS="LITERAL">WIDGETNAME_class_init()</TT>函数初始化构件类结构的域,并为类设置任何信号。我们的井字游戏构件是这样的:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">enum {  TICTACTOE_SIGNAL,  LAST_SIGNAL};static gint tictactoe_signals[LAST_SIGNAL] = { 0 };static voidtictactoe_class_init (TictactoeClass *class){  GtkObjectClass *object_class;  object_class = (GtkObjectClass*) class;    tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",					 GTK_RUN_FIRST,					 object_class-&#62;type,					 GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),					 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);  gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);  class-&#62;tictactoe = NULL;}</PRE></TD></TR></TABLE><P>我们的构件只有一个<TTCLASS="LITERAL">tictactoe</TT>信号,当连成一行、一列或一个对角线时,该信号被触发。并不是每个复合构件都需要信号,因此当你第一次阅读这节时,可以跳过看下一节,因为这一节对初学者有点难。</P><P>函数:</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">gint gtk_signal_new( const gchar         *name,                     GtkSignalRunType     run_type,                     GtkType              object_type,                     gint                 function_offset,                     GtkSignalMarshaller  marshaller,                     GtkType              return_val,                     guint                nparams,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -