📄 gtk_tut-8.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML><HEAD> <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9"> <TITLE>GTK v1.2 Tutorial: Range Widgets</TITLE> <LINK HREF="gtk_tut-9.html" REL=next> <LINK HREF="gtk_tut-7.html" REL=previous> <LINK HREF="gtk_tut.html#toc8" REL=contents></HEAD><BODY BGCOLOR="#FFFFFF"><A HREF="gtk_tut-9.html">Next</A><A HREF="gtk_tut-7.html">Previous</A><A HREF="gtk_tut.html#toc8">Contents</A><HR NOSHADE><H2><A NAME="sec_Range_Widgets"></A> <A NAME="s8">8. Range Widgets</A></H2><P>The category of range widgets includes the ubiquitous scrollbar widgetand the less common "scale" widget. Though these two types of widgetsare generally used for different purposes, they are quite similar infunction and implementation. All range widgets share a set of commongraphic elements, each of which has its own X window and receivesevents. They all contain a "trough" and a "slider" (what is sometimescalled a "thumbwheel" in other GUI environments). Dragging the sliderwith the pointer moves it back and forth within the trough, whileclicking in the trough advances the slider towards the location of theclick, either completely, or by a designated amount, depending onwhich mouse button is used.<P>As mentioned in <A HREF="gtk_tut-7.html#sec_Adjustment">Adjustments</A> above,all range widgets are associated with an adjustment object, from whichthey calculate the length of the slider and its position within thetrough. When the user manipulates the slider, the range widget willchange the value of the adjustment.<P><H2><A NAME="ss8.1">8.1 Scrollbar Widgets</A></H2><P>These are your standard, run-of-the-mill scrollbars. These should beused only for scrolling some other widget, such as a list, a text box,or a viewport (and it's generally easier to use the scrolled windowwidget in most cases). For other purposes, you should use scalewidgets, as they are friendlier and more featureful.<P>There are separate types for horizontal and vertical scrollbars.There really isn't much to say about these. You create them with thefollowing functions, defined in <CODE><gtk/gtkhscrollbar.h></CODE>and <CODE><gtk/gtkvscrollbar.h></CODE>:<P><BLOCKQUOTE><CODE><PRE>GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );</PRE></CODE></BLOCKQUOTE><P>and that's about it (if you don't believe me, look in the headerfiles!). The <CODE>adjustment</CODE> argument can either be a pointer to anexisting GtkAdjustment, or NULL, in which case one will be created foryou. Specifying NULL might actually be useful in this case, if youwish to pass the newly-created adjustment to the constructor functionof some other widget which will configure it for you, such as a textwidget.<H2><A NAME="ss8.2">8.2 Scale Widgets</A></H2><P>Scale widgets are used to allow the user to visually select andmanipulate a value within a specific range. You might want to use ascale widget, for example, to adjust the magnification level on azoomed preview of a picture, or to control the brightness of a colour,or to specify the number of minutes of inactivity before a screensavertakes over the screen.<P><H3>Creating a Scale Widget</H3><P>As with scrollbars, there are separate widget types for horizontal andvertical scale widgets. (Most programmers seem to favour horizontalscale widgets). Since they work essentially the same way, there's noneed to treat them separately here. The following functions, definedin <CODE><gtk/gtkvscale.h></CODE> and<CODE><gtk/gtkhscale.h></CODE>, create vertical and horizontal scalewidgets, respectively:<P><BLOCKQUOTE><CODE><PRE>GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );</PRE></CODE></BLOCKQUOTE><P>The <CODE>adjustment</CODE> argument can either be an adjustment which hasalready been created with <CODE>gtk_adjustment_new()</CODE>, or <CODE>NULL</CODE>, inwhich case, an anonymous GtkAdjustment is created with all of itsvalues set to <CODE>0.0</CODE> (which isn't very useful in this case). Inorder to avoid confusing yourself, you probably want to create youradjustment with a <CODE>page_size</CODE> of <CODE>0.0</CODE> so that its <CODE>upper</CODE>value actually corresponds to the highest value the user can select.(If you're <EM>already</EM> thoroughly confused, read the section on <A HREF="gtk_tut-7.html#sec_Adjustment">Adjustments</A> again for an explanation ofwhat exactly adjustments do and how to create and manipulate them).<P><H3>Functions and Signals (well, functions, at least)</H3><P>Scale widgets can display their current value as a number beside thetrough. The default behaviour is to show the value, but you can changethis with this function:<P><BLOCKQUOTE><CODE><PRE>void gtk_scale_set_draw_value( GtkScale *scale, gint draw_value );</PRE></CODE></BLOCKQUOTE><P>As you might have guessed, <CODE>draw_value</CODE> is either <CODE>TRUE</CODE> or<CODE>FALSE</CODE>, with predictable consequences for either one.<P>The value displayed by a scale widget is rounded to one decimal pointby default, as is the <CODE>value</CODE> field in its GtkAdjustment. You canchange this with:<P><BLOCKQUOTE><CODE><PRE>void gtk_scale_set_digits( GtkScale *scale, gint digits );</PRE></CODE></BLOCKQUOTE><P>where <CODE>digits</CODE> is the number of decimal places you want. You canset <CODE>digits</CODE> to anything you like, but no more than 13 decimalplaces will actually be drawn on screen.<P>Finally, the value can be drawn in different positionsrelative to the trough:<P><BLOCKQUOTE><CODE><PRE>void gtk_scale_set_value_pos( GtkScale *scale, GtkPositionType pos );</PRE></CODE></BLOCKQUOTE><P>The argument <CODE>pos</CODE> is of type <CODE>GtkPositionType</CODE>, which isdefined in <CODE><gtk/gtkenums.h></CODE>, and can take one of thefollowing values:<P><UL><LI> GTK_POS_LEFT</LI><LI> GTK_POS_RIGHT</LI><LI> GTK_POS_TOP</LI><LI> GTK_POS_BOTTOM</LI></UL><P>If you position the value on the "side" of the trough (e.g. on the topor bottom of a horizontal scale widget), then it will follow theslider up and down the trough.<P>All the preceding functions are defined in<CODE><gtk/gtkscale.h></CODE>.<H2><A NAME="sec_Range_Functions"></A> <A NAME="ss8.3">8.3 Common Functions </A></H2><P>The GtkRange widget class is fairly complicated internally, but, likeall the "base class" widgets, most of its complexity is onlyinteresting if you want to hack on it. Also, almost all of thefunctions and signals it defines are only really used in writingderived widgets. There are, however, a few useful functions that aredefined in <CODE><gtk/gtkrange.h></CODE> and will work on all rangewidgets.<P><H3>Setting the Update Policy</H3><P>The "update policy" of a range widget defines at what points duringuser interaction it will change the <CODE>value</CODE> field of itsGtkAdjustment and emit the "value_changed" signal on thisGtkAdjustment. The update policies, defined in<CODE><gtk/gtkenums.h></CODE> as type <CODE>enum GtkUpdateType</CODE>,are:<P><UL><LI>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The"value_changed" signal is emitted continuously, i.e. whenever theslider is moved by even the tiniest amount.</LI><LI>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal isonly emitted once the slider has stopped moving and the user hasreleased the mouse button.</LI><LI>GTK_UPDATE_POLICY_DELAYED - The "value_change" signal is emittedwhen the user releases the mouse button, or if the slider stops movingfor a short period of time.</LI></UL><P>The update policy of a range widget can be set by casting it using the<CODE>GTK_RANGE (Widget)</CODE> macro and passing it to this function:<P><BLOCKQUOTE><CODE><PRE>void gtk_range_set_update_policy( GtkRange *range, GtkUpdateType policy) ;</PRE></CODE></BLOCKQUOTE><P><H3>Getting and Setting Adjustments</H3><P>Getting and setting the adjustment for a range widget "on the fly" isdone, predictably, with:<P><BLOCKQUOTE><CODE><PRE>GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );void gtk_range_set_adjustment( GtkRange *range, GtkAdjustment *adjustment );</PRE></CODE></BLOCKQUOTE><P><CODE>gtk_range_get_adjustment()</CODE> returns a pointer to the adjustment towhich <CODE>range</CODE> is connected.<P><CODE>gtk_range_set_adjustment()</CODE> does absolutely nothing if you pass itthe adjustment that <CODE>range</CODE> is already using, regardless of whetheryou changed any of its fields or not. If you pass it a newGtkAdjustment, it will unreference the old one if it exists (possiblydestroying it), connect the appropriate signals to the new one, andcall the private function <CODE>gtk_range_adjustment_changed()</CODE>, whichwill (or at least, is supposed to...) recalculate the size and/orposition of the slider and redraw if necessary. As mentioned in thesection on adjustments, if you wish to reuse the same GtkAdjustment,when you modify its values directly, you should emit the "changed"signal on it, like this:<P><BLOCKQUOTE><CODE><PRE>gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");</PRE></CODE></BLOCKQUOTE><H2><A NAME="ss8.4">8.4 Key and Mouse bindings</A></H2><P>All of the GTK+ range widgets react to mouse clicks in more or lessthe same way. Clicking button-1 in the trough will cause itsadjustment's <CODE>page_increment</CODE> to be added or subtracted from its<CODE>value</CODE>, and the slider to be moved accordingly. Clicking mousebutton-2 in the trough will jump the slider to the point at which thebutton was clicked. Clicking any button on a scrollbar's arrows willcause its adjustment's value to change <CODE>step_increment</CODE> at a time.<P>It may take a little while to get used to, but by default, scrollbarsas well as scale widgets can take the keyboard focus in GTK+. If youthink your users will find this too confusing, you can always disablethis by unsetting the GTK_CAN_FOCUS flag on the scrollbar, like this:<P><BLOCKQUOTE><CODE><PRE>GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);</PRE></CODE></BLOCKQUOTE><P>The key bindings (which are, of course, only active when the widgethas focus) are slightly different between horizontal and verticalrange widgets, for obvious reasons. They are also not quite the samefor scale widgets as they are for scrollbars, for somewhat lessobvious reasons (possibly to avoid confusion between the keys forhorizontal and vertical scrollbars in scrolled windows, where bothoperate on the same area).<P><H3>Vertical Range Widgets</H3><P>All vertical range widgets can be operated with the up and down arrowkeys, as well as with the <CODE>Page Up</CODE> and <CODE>Page Down</CODE> keys. Thearrows move the slider up and down by <CODE>step_increment</CODE>, while<CODE>Page Up</CODE> and <CODE>Page Down</CODE> move it by <CODE>page_increment</CODE>.<P>The user can also move the slider all the way to one end or the otherof the trough using the keyboard. With the GtkVScale widget, this isdone with the <CODE>Home</CODE> and <CODE>End</CODE> keys, whereas with theGtkVScrollbar widget, this is done by typing <CODE>Control-Page Up</CODE>and <CODE>Control-Page Down</CODE>.<P><H3>Horizontal Range Widgets</H3><P>The left and right arrow keys work as you might expect in thesewidgets, moving the slider back and forth by <CODE>step_increment</CODE>. The<CODE>Home</CODE> and <CODE>End</CODE> keys move the slider to the ends of the trough.For the GtkHScale widget, moving the slider by <CODE>page_increment</CODE> isaccomplished with <CODE>Control-Left</CODE> and <CODE>Control-Right</CODE>,while for GtkHScrollbar, it's done with <CODE>Control-Home</CODE> and<CODE>Control-End</CODE>.<H2><A NAME="sec_Range_Example"></A> <A NAME="ss8.5">8.5 Example</A></H2><P>This example is a somewhat modified version of the "range controls"test from <CODE>testgtk.c</CODE>. It basically puts up a window with threerange widgets all connected to the same adjustment, and a couple ofcontrols for adjusting some of the parameters mentioned above and inthe seciton on adjustments, so you can see how they affect the waythese widgets work for the user.<P><BLOCKQUOTE><CODE><PRE>/* example-start rangewidgets rangewidgets.c */#include <gtk/gtk.h>GtkWidget *hscale, *vscale;void cb_pos_menu_select( GtkWidget *item, GtkPositionType pos )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -