?? sec-widgetindetail.html
字號:
<p> As you might expect, the <span class="STRUCTNAME"> unrealize</span> method reverses a widget's realization, freeing the resources created in <span class= "STRUCTNAME">realize</span>. The default unrealize method is appropriate for all widgets; it does the following: </p> <ul> <li> <p> Unmaps the widget if the widget is mapped; remember the GTK+ invariant that all mapped widgets are realized. </p> </li> <li> <p> Unrealizes all child widgets, if the widget is a container; this maintains the invariant that widgets cannot be realized unless their parents are also realized. </p> </li> <li> <p> Unreferences <span class="STRUCTNAME"> widget->style</span>. </p> </li> <li> <p> Destroys <span class="STRUCTNAME"> widget->window</span> (windowless widgets only unreference it). </p> </li> <li> <p> Unsets the <span class="STRUCTNAME"> GTK_REALIZED</span> flag. </p> </li> </ul> <p> Widgets are required to chain up if they override their base class's unrealize method. This ensures that all resources are freed. Overriding the default method may be necessary if a widget has more than one <span class= "STRUCTNAME">GdkWindow</span> or other special needs. All windows should be destroyed just as <tt class= "CLASSNAME">GtkEv</tt> destroys its <span class= "STRUCTNAME">event_window</span>, that is, the window's user data field should be set to <span class= "STRUCTNAME">NULL</span> before destruction: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> gdk_window_set_user_data(ev->event_window, NULL); gdk_window_destroy(ev->event_window); ev->event_window = NULL; </pre> </td> </tr> </table> <p> This keeps GTK+ from sending a useless <span class= "STRUCTNAME">GDK_DESTROY</span> event for the window. </p> <p> The <span class="SYMBOL">"unrealize"</span> signal is emitted via <tt class="FUNCTION"> gtk_widget_unrealize()</tt>. <tt class="FUNCTION"> gtk_widget_unrealize()</tt> does some internal bookkeeping which is important but not very interesting; just be careful to use this function rather than emitting the signal directly. </p> </div> <div class="SECT2"> <h2 class="SECT2"> <a name="Z157">Drawing</a> </h2> <p> The relationship between <span class="STRUCTNAME"> draw</span>, <span class="STRUCTNAME">draw_focus</span>, <span class="STRUCTNAME">draw_default</span>, and <span class="STRUCTNAME">expose_event</span> was discussed in <a href="z147.html#SEC-GTKEVDRAWING">the section called <i>Drawing</i></a>. All four class functions are registered as default handlers for a signal of the same name. The <span class="SYMBOL">"draw"</span> signal redraws a portion of the widget; it is emitted by GTK+ or by widget implementations. </p> <p> Widget implementations should emit the <span class= "SYMBOL">"draw_focus"</span> signal themselves, generally in response to focus events; the signal draws or undraws a frame indicating that the widget is focused. <tt class= "FUNCTION">gtk_window_set_default()</tt> emits the <span class="SYMBOL">"draw_default"</span> signal for both the widget losing default status and the widget gaining it. (<tt class="FUNCTION">gtk_widget_grab_default()</tt> calls <tt class="FUNCTION"> gtk_window_set_default()</tt>.) Only widgets with the <span class="STRUCTNAME">GTK_CAN_FOCUS</span> or <span class="STRUCTNAME">GTK_CAN_DEFAULT</span> flag set need to worry about the <span class="STRUCTNAME"> draw_focus</span> and <span class="STRUCTNAME"> draw_default</span> methods. These flags should be set in a widget's instance initialization function. </p> <p> Only the draw method has a default implementation in <tt class="CLASSNAME">GtkWidget</tt>; the default implementation synthesizes an expose event covering the widget's entire allocation. This allows you to write an expose event handler that also handles the draw signal. </p> <p> GTK+ normally emits the <span class="SYMBOL"> "draw"</span> signal in an idle function. That is, it keeps a list of widgets (and regions of them) that need to be redrawn; when no events are pending, the GTK+ main loop runs an idle function that traverses the list and emits the <span class="SYMBOL">"draw"</span> signal for each widget. Redraw areas are merged as much as possible to avoid multiple redraws, and the idle function is removed after it runs once. This arrangement minimizes the number of redraws and reduces flicker. </p> </div> <div class="SECT2"> <h2 class="SECT2"> <a name="SEC-SIZENEG">Size Negotiation</a> </h2> <p> The size negotiation process has already been described in <a href="sec-containers.html#SEC-SIZENEGOTIATION">the section called <i>Size Allocation</i> in the chapter called <i>GTK+ Basics</i></a> and <a href= "z147.html#SEC-GTKEVSIZENEG">the section called <i>Size Negotiation</i></a>. The two signals/methods involved are <span class="STRUCTNAME">size_request</span> and <span class="STRUCTNAME">size_allocate</span>. <tt class= "CLASSNAME">GtkWidget</tt> provides default implementations of each. </p> <p> Here is the default <span class="STRUCTNAME"> size_request</span> method: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> static voidgtk_widget_real_size_request (GtkWidget *widget, GtkRequisition *requisition){ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); requisition->width = widget->requisition.width; requisition->height = widget->requisition.height;} </pre> </td> </tr> </table> <p> This implementation is appropriate for widgets that always request the same size; <tt class="CLASSNAME"> GtkArrow</tt> and <tt class="CLASSNAME"> GtkDrawingArea</tt>, for example, use this default. Widgets using the default must initialize <span class= "STRUCTNAME">widget->requisition</span> with their fixed request; <span class="STRUCTNAME">GtkArrow</span> does this in <tt class="FUNCTION">gtk_arrow_init()</tt>. <tt class="CLASSNAME">GtkDrawingArea</tt> begins with a default size, but allows users to change the request with <tt class="FUNCTION">gtk_drawing_area_set_size()</tt>. </p> <p> Widgets whose request depends on their children, or the amount of text they contain, or some other factor, should override the default size request method with a method that calculates the size they want. </p> <p> Size allocation is mildly more complicated; here is its default implementation: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> static voidgtk_widget_real_size_allocate (GtkWidget *widget, GtkAllocation *allocation){ g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_WIDGET (widget)); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_NO_WINDOW (widget)) { gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); }} </pre> </td> </tr> </table> <p> This should suffice for most simple widgets. Widgets like <tt class="CLASSNAME">GtkEv</tt>, or any container, need to update internal data structures or distribute the allocation they receive among child widgets; these widgets will override <span class="STRUCTNAME"> size_allocate</span>. It is possible but not required to chain up to the default implementation. </p> <p> The wrapper function which emits the <span class= "SYMBOL">"size_allocate"</span> signal is significantly more involved than the signal handlers. <tt class= "FUNCTION">gtk_widget_size_allocate()</tt> takes into account <tt class="FUNCTION">gtk_widget_set_usize()</tt> and ensures widgets are redrawn if their size changes. (Unsurprisingly, <tt class="FUNCTION"> gtk_widget_size_request()</tt> also exists and should be used instead of emitting <span class="SYMBOL"> "size_request"</span> directly.) </p> </div> <div class="SECT2"> <h2 class="SECT2"> <a name="Z158"><tt class="CLASSNAME"> GtkContainer</tt></a> </h2> <p> <tt class="CLASSNAME">GtkContainer</tt> is the base class for all widgets that contain one or more other widgets. <tt class="CLASSNAME">GtkBin</tt> is a subclass of <tt class="CLASSNAME">GtkContainer</tt>, and is the base class for widgets with a single child. </p> <div class="SECT3"> <h3 class="SECT3"> <a name="Z159">The <tt class="CLASSNAME"> GtkContainer</tt> Instance Struct</a> </h3> <p> Here is <tt class="CLASSNAME">GtkContainer</tt>: </p> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING"> typedef struct _GtkContainer GtkContainer;struct _GtkContainer{ GtkWidget widget; GtkWidget *focus_child; guint border_width : 16; guint need_resize : 1; guint resize_mode : 2; GSList *resize_widgets;}; </pre> </td> </tr> </table> <p> The <span class="STRUCTNAME">focus_child</span> member is the child in the container with the keyboard focus; it can be <span class="STRUCTNAME">NULL</span> if no child has the focus. The <tt class="CLASSNAME"> GtkContainer</tt> implementation handles setting and unsetting this field. The <span class="STRUCTNAME"> border_width</span> member is a width in pixels to add to the container's size request on all sides; the container will also subtract this value from its allocation. (In other words, the <span class= "STRUCTNAME">border_width</span> is a blank space around the container.) Library users set the <span class="STRUCTNAME">border_width</span> field with <tt class="FUNCTION">gtk_container_set_border_width()</tt>; <tt class="CLASSNAME">GtkContainer</tt> subclasses must honor its value in their <span class="STRUCTNAME"> size_request</span> and <span class="STRUCTNAME"> size_allocate</span> implementations. </p> <p> The <span class="STRUCTNAME">need_resize</span>, <span class="STRUCTNAME">resize_mode</span>, and <span class= "STRUCTNAME">resize_widgets</span> fields are implementation details that subclasses should not have to read or modify. These fields are used to implement <tt class="FUNCTION">gtk_widget_queue_resize()</tt>; when a resize is queued for a widget, the <tt class= "CLASSNAME">GtkContainer</tt> implementation ensures that the size negotiation process (requisition/allocation) will take place a in a one-shot idle handler. Subclasses of <tt class= "CLASSNAME">GtkContainer</tt> simply implement <span class="STRUCTNAME">size_request</span> and <span class= "STRUCTNAME">size_allocate</span>, and everything works. </p> </div> <div class="SECT3"> <h3 class="SECT3"> <a name="Z160">The <tt class="CLASSNAME"> GtkContainer</tt> Class Struct</a> </h3> <table border="0" bgcolor="#E0E0E0" width="100%"> <tr> <td><pre class="PROGRAMLISTING">
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -