?? z147.html
字號:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html> <head> <title> An Example: The GtkEv Widget </title> <meta name="GENERATOR" content= "Modular DocBook HTML Stylesheet Version 1.45"> <link rel="HOME" title="GTK+ / Gnome Application Development" href="ggad.html"> <link rel="UP" title="Writing a GtkWidget" href= "cha-widget.html"> <link rel="PREVIOUS" title="The GtkWidget Base Class" href= "z144.html"> <link rel="NEXT" title="GtkWidget In Detail" href= "sec-widgetindetail.html"> </head> <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink= "#840084" alink="#0000FF"> <div class="NAVHEADER"> <table width="100%" border="0" bgcolor="#ffffff" cellpadding= "1" cellspacing="0"> <tr> <th colspan="4" align="center"> <font color="#000000" size="2">GTK+ / Gnome Application Development</font> </th> </tr> <tr> <td width="25%" bgcolor="#ffffff" align="left"> <a href="z144.html"><font color="#0000ff" size="2"><b> <<< Previous</b></font></a> </td> <td width="25%" colspan="2" bgcolor="#ffffff" align= "center"> <font color="#0000ff" size="2"><b><a href="ggad.html"> <font color="#0000ff" size="2"><b> Home</b></font></a></b></font> </td> <td width="25%" bgcolor="#ffffff" align="right"> <a href="sec-widgetindetail.html"><font color="#0000ff" size="2"><b>Next >>></b></font></a> </td> </tr> </table> </div> <div class="SECT1"> <h1 class="SECT1"> <a name="Z147">An Example: The <tt class="CLASSNAME"> GtkEv</tt> Widget</a> </h1> <p> This section describes a very simple widget called <tt class="CLASSNAME">GtkEv</tt>, inspired by the <tt class= "APPLICATION">xev</tt> client that comes with X. <tt class= "CLASSNAME">GtkEv</tt> has two components: a small sub-window that receives events, and a larger window where information about each event is reported. <a href= "z147.html#FIG-GTKEV">Figure 1</a> shows <tt class= "CLASSNAME">GtkEv</tt> in action. The complete <tt class= "CLASSNAME">GtkEv</tt> source code is in Appendix E. <tt class="CLASSNAME">GtkEv</tt> would be a lovely way to implement an <tt class="APPLICATION">xev</tt>-style application for Gnome; it packages the core application functionality in a nice module. </p> <div class="FIGURE"> <a name="FIG-GTKEV"></a> <p> <img src="figures/gtkev.png"> </p> <p> <b>Figure 1. The <tt class="CLASSNAME">GtkEv</tt> widget. Events are reported for the white subwindow.</b> </p> </div> <div class="SECT2"> <h2 class="SECT2"> <a name="Z148">Overview</a> </h2> <p> <tt class="CLASSNAME">GtkEv</tt> uses two <span class= "STRUCTNAME">GdkWindow</span>s; the larger one, <tt class="CLASSNAME">GtkEv</tt>'s <span class="STRUCTNAME"> widget->window</span>, has a gray background and is used to render text describing each event. The smaller one is a child of the primary window, and is the window the widget reports events for. </p> <p> Here are the class and instance structs for <tt class= "CLASSNAME">GtkEv</tt>: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> typedef struct _GtkEv GtkEv;typedef struct _GtkEvClass GtkEvClass;struct _GtkEv{ GtkWidget widget; GdkWindow* event_window; GdkRectangle event_window_rect; GdkRectangle description_rect; GList* buffer; GList* buffer_end; gint buffer_size;};struct _GtkEvClass{ GtkWidgetClass parent_class;}; </pre> </td> </tr> </table> <p> As you can see, <tt class="CLASSNAME">GtkEv</tt> has no class functions or signals of its own. Each instance stores a pointer to the small event window in <span class="STRUCTNAME">event_window</span>. Two rectangles cache the area covered by the event window, and the area covered by the event description text. The widget's allocation is divided between these two areas. Finally, <tt class="CLASSNAME">GtkEv</tt> stores a list of string vectors describing events; it caches the end of the list and the length of the list. As events are received, text describing them is pushed on to the front of the buffer. When the list becomes too long to fit on the screen, <tt class="CLASSNAME">GtkEv</tt> removes an event from the back of the buffer each time it adds a new event to the front, keeping the buffer size constant. </p> </div> <div class="SECT2"> <h2 class="SECT2"> <a name="Z149"><span class="STRUCTNAME">GtkObject</span> Features</a> </h2> <p> Like all <span class="STRUCTNAME">GtkObject</span>s, <tt class="CLASSNAME">GtkEv</tt> provides for its creation and destruction. </p> <div class="SECT3"> <h3 class="SECT3"> <a name="Z150">Creation</a> </h3> <p> <tt class="CLASSNAME">GtkEv</tt>'s init, class init, and constructor functions are pure boilerplate and should require no explanation; here they are, to help you get oriented: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> static GtkWidgetClass *parent_class = NULL;guintgtk_ev_get_type (void){ static guint ev_type = 0; if (!ev_type) { static const GtkTypeInfo ev_info = { "GtkEv", sizeof (GtkEv), sizeof (GtkEvClass), (GtkClassInitFunc) gtk_ev_class_init, (GtkObjectInitFunc) gtk_ev_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; ev_type = gtk_type_unique (gtk_widget_get_type (), &ev_info); } return ev_type;}static voidgtk_ev_class_init (GtkEvClass *klass){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass*) klass; widget_class = (GtkWidgetClass*) klass; parent_class = gtk_type_class (gtk_widget_get_type ()); object_class->destroy = gtk_ev_destroy; widget_class->realize = gtk_ev_realize; widget_class->unrealize = gtk_ev_unrealize; widget_class->size_request = gtk_ev_size_request; widget_class->size_allocate = gtk_ev_size_allocate; widget_class->draw = gtk_ev_draw; widget_class->event = gtk_ev_event; widget_class->draw_focus = gtk_ev_draw_focus; widget_class->expose_event = gtk_ev_expose; widget_class->focus_in_event = gtk_ev_focus_in; widget_class->focus_out_event = gtk_ev_focus_out;}static voidgtk_ev_init (GtkEv *ev){ GTK_WIDGET_SET_FLAGS (GTK_WIDGET(ev), GTK_CAN_FOCUS); ev->event_window = NULL; ev->buffer = NULL; ev->buffer_end = NULL; ev->buffer_size = 0; ev->event_window_rect.x = ev->event_window_rect.y = 0; ev->event_window_rect.width = ev->event_window_rect.height = 0; ev->description_rect.x = ev->description_rect.y = 0; ev->description_rect.width = ev->description_rect.height = 0;}GtkWidget*gtk_ev_new (void){ GtkEv *ev; ev = gtk_type_new (gtk_ev_get_type ()); return GTK_WIDGET (ev);} </pre> </td> </tr> </table> </div> <div class="SECT3"> <h3 class="SECT3"> <a name="Z151">Destruction</a> </h3> <p> <tt class="CLASSNAME">GtkEv</tt> overrides only the <span class="STRUCTNAME">destroy</span> method from <span class="STRUCTNAME">GtkObject</span>, to clean up the event description buffer. The widget's windows will be destroyed in <tt class="CLASSNAME">GtkWidget</tt>'s shutdown method, which unrealizes the widget. <tt class="CLASSNAME">GtkWidget</tt>'s finalize method cleans up some <tt class="CLASSNAME">GtkWidget</tt> resources and then chains to the <span class= "STRUCTNAME">GtkObject</span> method which frees the instance struct. (Refer to <a href= "sec-finalization.html">the section called <i>Object Finalization</i> in the chapter called <i>The GTK+ Object and Type System</i></a> for more details on these methods.) </p> <p> Because <tt class="CLASSNAME">GtkEv</tt> has no object arguments, it does not need to implement <span class= "STRUCTNAME">get_arg</span> or <span class= "STRUCTNAME">set_arg</span> methods. </p> <p> Here is its destroy method implementation: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> static void gtk_ev_destroy (GtkObject *object){ GtkEv* ev; GList* tmp; g_return_if_fail(object != NULL); g_return_if_fail(GTK_IS_EV(object)); ev = GTK_EV(object); tmp = ev->buffer; while (tmp != NULL) { g_strfreev((gchar**)tmp->data); tmp = g_list_next(tmp); } g_list_free(ev->buffer); ev->buffer = NULL; ev->buffer_end = NULL; ev->buffer_size = 0; /* Chain up */ if (GTK_OBJECT_CLASS(parent_class)->destroy) (* GTK_OBJECT_CLASS(parent_class)->destroy) (object);} </pre> </td> </tr> </table> <p> The only detail worthy of note is that freed pointers are set to <span class="STRUCTNAME">NULL</span>, because a destroyed object should remain "sane," unlike a finalized object. The <tt class="CLASSNAME"> GtkEv</tt> code depends on the fact that destroyed widgets are always unrealized; otherwise, text could be re-added to the buffer after destruction but before finalization, and a finalize method would be required. </p> </div> </div> <div class="SECT2"> <h2 class="SECT2"> <a name="Z152">Realization and Mapping</a> </h2>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -