📄 gtk_tut-12.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: Tree Widget </TITLE> <LINK HREF="gtk_tut-13.html" REL=next> <LINK HREF="gtk_tut-11.html" REL=previous> <LINK HREF="gtk_tut.html#toc12" REL=contents></HEAD><BODY BGCOLOR="#FFFFFF"><A HREF="gtk_tut-13.html">Next</A><A HREF="gtk_tut-11.html">Previous</A><A HREF="gtk_tut.html#toc12">Contents</A><HR NOSHADE><H2><A NAME="sec_Tree_Widgets"></A> <A NAME="s12">12. Tree Widget </A></H2><P>The purpose of tree widgets is to display hierarchically-organizeddata. The GtkTree widget itself is a vertical container for widgets oftype GtkTreeItem. GtkTree itself is not terribly different fromGtkList - both are derived directly from GtkContainer, and theGtkContainer methods work in the same way on GtkTree widgets as onGtkList widgets. The difference is that GtkTree widgets can be nestedwithin other GtkTree widgets. We'll see how to do this shortly.<P>The GtkTree widget has its own window, and defaults to a whitebackground, as does GtkList. Also, most of the GtkTree methods work inthe same way as the corresponding GtkList ones. However, GtkTree isnot derived from GtkList, so you cannot use them interchangeably.<P><H2><A NAME="ss12.1">12.1 Creating a Tree</A></H2><P>A GtkTree is created in the usual way, using:<P><BLOCKQUOTE><CODE><PRE>GtkWidget *gtk_tree_new( void );</PRE></CODE></BLOCKQUOTE><P>Like the GtkList widget, a GtkTree will simply keep growing as moreitems are added to it, as well as when subtrees are expanded. Forthis reason, they are almost always packed into aGtkScrolledWindow. You might want to use gtk_widget_set_usize() on thescrolled window to ensure that it is big enough to see the tree'sitems, as the default size for GtkScrolledWindow is quite small.<P>Now that you have a tree, you'll probably want to add some items toit. <A HREF="#sec_Tree_Item_Widget">The Tree Item Widget</A> belowexplains the gory details of GtkTreeItem. For now, it'll suffice tocreate one, using:<P><BLOCKQUOTE><CODE><PRE>GtkWidget *gtk_tree_item_new_with_label( gchar *label );</PRE></CODE></BLOCKQUOTE><P>You can then add it to the tree using one of the following (see<A HREF="#sec_GtkTree_Functions">Functions and Macros</A>below for more options):<P><BLOCKQUOTE><CODE><PRE>void gtk_tree_append( GtkTree *tree, GtkWidget *tree_item );void gtk_tree_prepend( GtkTree *tree, GtkWidget *tree_item );</PRE></CODE></BLOCKQUOTE><P>Note that you must add items to a GtkTree one at a time - there is noequivalent to gtk_list_*_items().<P><H2><A NAME="ss12.2">12.2 Adding a Subtree</A></H2><P>A subtree is created like any other GtkTree widget. A subtree is addedto another tree beneath a tree item, using:<P><BLOCKQUOTE><CODE><PRE>void gtk_tree_item_set_subtree( GtkTreeItem *tree_item, GtkWidget *subtree );</PRE></CODE></BLOCKQUOTE><P>You do not need to call gtk_widget_show() on a subtree before or afteradding it to a GtkTreeItem. However, you <EM>must</EM> have added theGtkTreeItem in question to a parent tree before callinggtk_tree_item_set_subtree(). This is because, technically, the parentof the subtree is <EM>not</EM> the GtkTreeItem which "owns" it, butrather the GtkTree which holds that GtkTreeItem.<P>When you add a subtree to a GtkTreeItem, a plus or minus sign appearsbeside it, which the user can click on to "expand" or "collapse" it,meaning, to show or hide its subtree. GtkTreeItems are collapsed bydefault. Note that when you collapse a GtkTreeItem, any selecteditems in its subtree remain selected, which may not be what the userexpects.<P><H2><A NAME="ss12.3">12.3 Handling the Selection List</A></H2><P>As with GtkList, the GtkTree type has a <CODE>selection</CODE> field, andit is possible to control the behaviour of the tree (somewhat) bysetting the selection type using:<P><BLOCKQUOTE><CODE><PRE>void gtk_tree_set_selection_mode( GtkTree *tree, GtkSelectionMode mode );</PRE></CODE></BLOCKQUOTE><P>The semantics associated with the various selection modes aredescribed in the section on the GtkList widget. As with the GtkListwidget, the "select_child", "unselect_child" (not really - see <A HREF="#sec_GtkTree_Signals">Signals</A> below for an explanation),and "selection_changed" signals are emitted when list items areselected or unselected. However, in order to take advantage of thesesignals, you need to know <EM>which</EM> GtkTree widget they will beemitted by, and where to find the list of selected items.<P>This is a source of potential confusion. The best way to explain thisis that though all GtkTree widgets are created equal, some are moreequal than others. All GtkTree widgets have their own X window, andcan therefore receive events such as mouse clicks (if theirGtkTreeItems or their children don't catch them first!). However, tomake GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection typesbehave in a sane manner, the list of selected items is specific to thetopmost GtkTree widget in a hierarchy, known as the "root tree".<P>Thus, accessing the <CODE>selection</CODE>field directly in an arbitraryGtkTree widget is not a good idea unless you <EM>know</EM> it's theroot tree. Instead, use the GTK_TREE_SELECTION (Tree) macro, whichgives the root tree's selection list as a GList pointer. Of course,this list can include items that are not in the subtree in question if the selection type is GTK_SELECTION_MULTIPLE.<P>Finally, the "select_child" (and "unselect_child", in theory) signalsare emitted by all trees, but the "selection_changed" signal is onlyemitted by the root tree. Consequently, if you want to handle the"select_child" signal for a tree and all its subtrees, you will haveto call gtk_signal_connect() for every subtree.<P><H2><A NAME="ss12.4">12.4 Tree Widget Internals</A></H2><P>The GtkTree's struct definition looks like this:<P><BLOCKQUOTE><CODE><PRE>struct _GtkTree{ GtkContainer container; GList *children; GtkTree* root_tree; /* owner of selection list */ GtkWidget* tree_owner; GList *selection; guint level; guint indent_value; guint current_indent; guint selection_mode : 2; guint view_mode : 1; guint view_line : 1;};</PRE></CODE></BLOCKQUOTE><P>The perils associated with accessing the <CODE>selection</CODE> fielddirectly have already been mentioned. The other important fields ofthe struct can also be accessed with handy macros or class functions.GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicateswhether a tree is the root tree in a GtkTree hierarchy, whileGTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of typeGtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you wantto use one of the gtk_widget_*() functions on it).<P>Instead of directly accessing the children field of a GtkTree widget,it's probably best to cast it using GTK_CONTAINER (Tree), and pass itto the gtk_container_children() function. This creates a duplicate ofthe original list, so it's advisable to free it up using g_list_free()after you're done with it, or to iterate on it destructively, likethis:<P><BLOCKQUOTE><CODE><PRE> children = gtk_container_children (GTK_CONTAINER (tree)); while (children) { do_something_nice (GTK_TREE_ITEM (children->data)); children = g_list_remove_link (children, children);}</PRE></CODE></BLOCKQUOTE><P>The <CODE>tree_owner</CODE> field is defined only in subtrees, where itpoints to the GtkTreeItem widget which holds the tree in question.The <CODE>level</CODE> field indicates how deeply nested a particular treeis; root trees have level 0, and each successive level of subtrees hasa level one greater than the parent level. This field is set onlyafter a GtkTree widget is actually mapped (i.e. drawn on the screen).<P><H3><A NAME="sec_GtkTree_Signals"></A> Signals</H3><P><BLOCKQUOTE><CODE><PRE>void selection_changed( GtkTree *tree );</PRE></CODE></BLOCKQUOTE><P>This signal will be emitted whenever the <CODE>selection</CODE> field of aGtkTree has changed. This happens when a child of the GtkTree isselected or deselected.<P><BLOCKQUOTE><CODE><PRE>void select_child( GtkTree *tree, GtkWidget *child );</PRE></CODE></BLOCKQUOTE><P>This signal is emitted when a child of the GtkTree is about to getselected. This happens on calls to gtk_tree_select_item(),gtk_tree_select_child(), on <EM>all</EM> button presses and calls togtk_tree_item_toggle() and gtk_item_toggle(). It may sometimes beindirectly triggered on other occasions where children get added to orremoved from the GtkTree.<P><BLOCKQUOTE><CODE><PRE>void unselect_child (GtkTree *tree, GtkWidget *child);</PRE></CODE></BLOCKQUOTE><P>This signal is emitted when a child of the GtkTree is about to getdeselected. As of GTK+ 1.0.4, this seems to only occur on calls togtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps onother occasions, but <EM>not</EM> when a button press deselects achild, nor on emission of the "toggle" signal by gtk_item_toggle().<P><H3><A NAME="sec_GtkTree_Functions"></A> Functions and Macros</H3><P><BLOCKQUOTE><CODE><PRE>guint gtk_tree_get_type( void );</PRE></CODE></BLOCKQUOTE><P>Returns the `GtkTree' type identifier.<P><BLOCKQUOTE><CODE><PRE>GtkWidget* gtk_tree_new( void );</PRE></CODE></BLOCKQUOTE><P>Create a new GtkTree object. The new widget is returned as a pointerto a GtkWidget object. NULL is returned on failure.<P><BLOCKQUOTE><CODE><PRE>void gtk_tree_append( GtkTree *tree, GtkWidget *tree_item );</PRE></CODE></BLOCKQUOTE><P>Append a tree item to a GtkTree.<P><BLOCKQUOTE><CODE><PRE>void gtk_tree_prepend( GtkTree *tree, GtkWidget *tree_item );</PRE></CODE></BLOCKQUOTE><P>Prepend a tree item to a GtkTree.<P><BLOCKQUOTE><CODE><PRE>void gtk_tree_insert( GtkTree *tree, GtkWidget *tree_item, gint position );</PRE></CODE></BLOCKQUOTE><P>Insert a tree item into a GtkTree at the position in the listspecified by <CODE>position.</CODE><P><BLOCKQUOTE><CODE><PRE>void gtk_tree_remove_items( GtkTree *tree, GList *items );</PRE></CODE></BLOCKQUOTE><P>Remove a list of items (in the form of a GList *) from a GtkTree.Note that removing an item from a tree dereferences (and thus usually)destroys it <EM>and</EM> its subtree, if it has one, <EM>and</EM> allsubtrees in that subtree. If you want to remove only one item, youcan use gtk_container_remove().<P><BLOCKQUOTE><CODE><PRE>void gtk_tree_clear_items( GtkTree *tree,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -