Linux 版 (精华区)

发信人: netiscpu (平淡是真), 信区: Linux
标  题: GTK入门导引(12)
发信站: 紫 丁 香 (Mon Dec 14 14:44:31 1998), 转信



发信人: hey (吟风·悠游98), 信区: Unix
标  题: GTK入门导引(12)
发信站: 华南网木棉站 (Tue Nov 10 11:11:49 1998), 转信

12. List物件

GtkList物件被设计成是个vertical container, 而在其中的物件必须是
GtkListItem. 

GtkList物件有其自己的视窗用来接取事件, 而其背景色一般是白色的. 由于它
是由GtkContainer而来, 您也可以用GTK_CONTAINER(List)巨集来处理. 请
见GtkContainer物件一章. 您应该已经熟悉GList的用法, 及其相关函数
g_list_*(), 这样您才不会在此遭遇到问题. 

在GtkList物件有一栏对我们来说很重要. 

    struct _GtkList
    {
      [...]
      GList *selection;
      guint selection_mode;
      [...]
    }; 

GtkList的selection栏指向一个所有items的link list, 其中记录所有被记录的项
目, 若为`NULL'则selection为空的. 因此要知道目前的selection, 我们可以读取
GTK_LIST()->selection一栏. 但不要修改它们, 因为它们是由内部所维护. 

GtkList的selection_mode决定selection的机制, 而GTK_LIST()->selection
栏的内容为: 

selection_mode可以是以下其中一种: 

    GTK_SELECTION_SINGLE selection可以是`NULL' 或对一个已选
    项目, 包含一个GList* pointer. 
    GTK_SELECTION_BROWSE 若list没有有效的物件, selection可以
    是`NULL' 否则它会包含一个GList* pointer, 而且就是一个list item. 
    GTK_SELECTION_MULTIPLE 若list中没有item被选取, selection
    可以是`NULL' 否则会有一个GList* pointer, 并且指向第一个selected
    item. 并一直向后接到第二个... 
    GTK_SELECTION_EXTENDED selection永远为`NULL'. 

内定为GTK_SELECTION_MULTIPLE. 

12.1 信号 

    void GtkList::selection_changed (GtkList *LIST)

当selection区域改变的时候, 这个信号会被触发. 这会在当GtkList的子物件被
select或unselect时发生. 

    void GtkList::select_child (GtkList *LIST, GtkWidget *CHILD)

当GtkList的子物件被select时, 这个信号会被触发. 这一般在
gtk_list_select_item(), gtk_list_select_child(), 按钮被按下及有时间接触发或
有子物件新增或移除时发生. 

    void GtkList::unselect_child (GtkList *LIST, GtkWidget *CHILD)

当GtkList的子物件被unselect时, 这个信号会被触发. 这一般在
gtk_list_unselect_item(), gtk_list_unselect_child(), 按钮被按下及有时间接触
发或有子物件新增或移除时发生. 

12.2 函数 

    guint gtk_list_get_type (void)

返回`GtkList' type identifier. 

    GtkWidget* gtk_list_new (void)

产生新的`GtkList' object. 新的物件其返回值为`GtkWidget' object的指标.
`NULL'表示失败. 

    void gtk_list_insert_items (GtkList *LIST, GList *ITEMS, gint POSITION)

插入list items到LIST里面, 由POSITION开始. ITEMS是双向链结串列. 每个
项目要指向一个产生出来的GtkListItem. 

    void gtk_list_append_items (GtkList *LIST, GList *ITEMS)

就像gtk_list_insert_items()一样插入ITEMS到LIST后面. 

    void gtk_list_prepend_items (GtkList *LIST, GList *ITEMS)

就如gtk_list_insert_items()一样插入ITEMS到LIST前面. 

    void gtk_list_remove_items (GtkList *LIST, GList *ITEMS)

从LIST中移除list items. ITEMS是双向链结串列, 每个node要指向child. 设计
者要自行呼叫g_list_free(ITEMS). 设计者也要自行处理掉list items. 

    void gtk_list_clear_items (GtkList *LIST, gint START, gint END)

从LIST中移除并销毁list items. 

    void gtk_list_select_item (GtkList *LIST, gint ITEM)

透过在LIST中目前的位置,触发GtkList::select_child信号给指定的list item. 

    void gtk_list_unselect_item (GtkList *LIST, gint ITEM)

透过在LIST中目前的位置,触发GtkList::unselect_child信号给指定的list item. 

    void gtk_list_select_child (GtkList *LIST, GtkWidget *CHILD)

触发GtkList::select_child信号给指定的CHILD. 

    void gtk_list_unselect_child (GtkList *LIST, GtkWidget *CHILD)

触发GtkList::unselect_child信号给指定的CHILD. 

    gint gtk_list_child_position (GtkList *LIST, GtkWidget *CHILD)

返回CHILD在LIST中的位置. `-1'为失败. 

    void gtk_list_set_selection_mode (GtkList *LIST, GtkSelectionMode MODE)

设定LIST到选择模式MODE, 可以是GTK_SELECTION_SINGLE,
GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE 或
GTK_SELECTION_EXTENDED. 

    GtkList* GTK_LIST (gpointer OBJ)

传一个generic pointer到`GtkList*'. *Note Standard Macros::, for more info. 

    GtkListClass* GTK_LIST_CLASS (gpointer CLASS)

传一个generic pointer到`GtkListClass*'. *Note Standard Macros::, for more
info. 

    gint GTK_IS_LIST (gpointer OBJ)

决定是否一个generic pointer对应到`GtkList' object. *Note Standard
Macros::, for more info. 

12.3 范例 

以下是个范例程式, 将会列出GtkList的选择改变, 并让您用滑鼠右键"逮捕"list
items. 


    /* compile this program with:
     * $ gcc -I/usr/local/include/ -lgtk -lgdk -lglib -lX11 -lm -Wall main.c
     */

    /* include the gtk+ header files
     * include stdio.h, we need that for the printf() function
     */
    #include        <gtk/gtk.h>
    #include        <stdio.h>

    /* this is our data identification string to store
     * data in list items
     */
    const   gchar   *list_item_data_key="list_item_data";


    /* prototypes for signal handler that we are going to connect
     * to the GtkList widget
     */
    static  void    sigh_print_selection    (GtkWidget      *gtklist,
                                             gpointer       func_data);
    static  void    sigh_button_event       (GtkWidget      *gtklist,
                                             GdkEventButton *event,
                                             GtkWidget      *frame);


    /* main function to set up the user interface */

    gint main (int argc, gchar *argv[])
    {                                  
        GtkWidget       *separator;
        GtkWidget       *window;
        GtkWidget       *vbox;
        GtkWidget       *scrolled_window;
        GtkWidget       *frame;
        GtkWidget       *gtklist;
        GtkWidget       *button;
        GtkWidget       *list_item;
        GList           *dlist;
        guint           i;
        gchar           buffer[64];
        
        
        /* initialize gtk+ (and subsequently gdk) */

        gtk_init(&argc, &argv);
        
        
        /* create a window to put all the widgets in
         * connect gtk_main_quit() to the "destroy" event of
         * the window to handle window manager close-window-events
         */
        window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
        gtk_signal_connect(GTK_OBJECT(window),
                           "destroy",
                           GTK_SIGNAL_FUNC(gtk_main_quit),
                           NULL);
        
        
        /* inside the window we need a box to arrange the widgets
         * vertically */
        vbox=gtk_vbox_new(FALSE, 5);
        gtk_container_border_width(GTK_CONTAINER(vbox), 5);
        gtk_container_add(GTK_CONTAINER(window), vbox);
        gtk_widget_show(vbox);
        
        /* this is the scolled window to put the GtkList widget inside */
        scrolled_window=gtk_scrolled_window_new(NULL, NULL);
        gtk_widget_set_usize(scrolled_window, 250, 150);
        gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
        gtk_widget_show(scrolled_window);
        
        /* create the GtkList widget
         * connect the sigh_print_selection() signal handler
         * function to the "selection_changed" signal of the GtkList
         * to print out the selected items each time the selection
         * has changed */
        gtklist=gtk_list_new();
        gtk_container_add(GTK_CONTAINER(scrolled_window), gtklist);
        gtk_widget_show(gtklist);
        gtk_signal_connect(GTK_OBJECT(gtklist),
                           "selection_changed",
                           GTK_SIGNAL_FUNC(sigh_print_selection),
                           NULL);
        
        /* we create a "Prison" to put a list item in ;)
         */
        frame=gtk_frame_new("Prison");
        gtk_widget_set_usize(frame, 200, 50);
        gtk_container_border_width(GTK_CONTAINER(frame), 5);
        gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
        gtk_container_add(GTK_CONTAINER(vbox), frame);
        gtk_widget_show(frame);
        
        /* connect the sigh_button_event() signal handler to the GtkList
         * wich will handle the "arresting" of list items
         */
        gtk_signal_connect(GTK_OBJECT(gtklist),
                           "button_release_event",
                           GTK_SIGNAL_FUNC(sigh_button_event),
                           frame);
        
        /* create a separator
         */
        separator=gtk_hseparator_new();
        gtk_container_add(GTK_CONTAINER(vbox), separator);
        gtk_widget_show(separator);
        
        /* finaly create a button and connect it愀 "clicked" signal
         * to the destroyment of the window
         */
        button=gtk_button_new_with_label("Close");
        gtk_container_add(GTK_CONTAINER(vbox), button);
        gtk_widget_show(button);
        gtk_signal_connect_object(GTK_OBJECT(button),
                                  "clicked",
                                  GTK_SIGNAL_FUNC(gtk_widget_destroy),
                                  GTK_OBJECT(window));
        
        
        /* now we create 5 list items, each having it愀 own
         * label and add them to the GtkList using gtk_container_add()
         * also we query the text string from the label and
         * associate it with the list_item_data_key for each list item
         */
        for (i=0; i<5; i++) {
            GtkWidget       *label;
            gchar           *string;
            
            sprintf(buffer, "ListItemContainer with Label #%d", i);
            label=gtk_label_new(buffer);
            list_item=gtk_list_item_new();
            gtk_container_add(GTK_CONTAINER(list_item), label);
            gtk_widget_show(label);
            gtk_container_add(GTK_CONTAINER(gtklist), list_item);
            gtk_widget_show(list_item);
            gtk_label_get(GTK_LABEL(label), &string);
            gtk_object_set_data(GTK_OBJECT(list_item),
                                list_item_data_key,
                                string);
        }
        /* here, we are creating another 5 labels, this time
         * we use gtk_list_item_new_with_label() for the creation
         * we can□ query the text string from the label because
         * we don□ have the labels pointer and therefore
         * we just associate the list_item_data_key of each
         * list item with the same text string
         * for adding of the list items we put them all into a doubly
         * linked list (GList), and then add them by a single call to
         * gtk_list_append_items()
         * because we use g_list_prepend() to put the items into the
         * doubly linked list, their order will be descending (instead
         * of ascending when using g_list_append())
         */
        dlist=NULL;
        for (; i<10; i++) {
            sprintf(buffer, "List Item with Label %d", i);
            list_item=gtk_list_item_new_with_label(buffer);
            dlist=g_list_prepend(dlist, list_item);
            gtk_widget_show(list_item);
            gtk_object_set_data(GTK_OBJECT(list_item),
                                list_item_data_key,
                                "ListItem with integrated Label");
        }
        gtk_list_append_items(GTK_LIST(gtklist), dlist);
        
        /* finaly we want to see the window, don□ we? ;)
         */
        gtk_widget_show(window);
        
        /* fire up the main event loop of gtk
         */
        gtk_main();
        
        /* we get here after gtk_main_quit() has been called which
         * happens if the main window gets destroyed
         */
        return 0;
    }

    /* this is the signal handler that got connected to button
     * press/release events of the GtkList
     */
    void
    sigh_button_event       (GtkWidget      *gtklist,
                             GdkEventButton *event,
                             GtkWidget      *frame)
    {
        /* we only do something if the third (rightmost mouse button
         * was released
         */
        if (event->type==GDK_BUTTON_RELEASE &&
            event->button==3) {
            GList           *dlist, *free_list;
            GtkWidget       *new_prisoner;
            
            /* fetch the currently selected list item which
             * will be our next prisoner ;)
             */
            dlist=GTK_LIST(gtklist)->selection;
            if (dlist)
                    new_prisoner=GTK_WIDGET(dlist->data);
            else
                    new_prisoner=NULL;
            
            /* look for already prisoned list items, we
             * will put them back into the list
             * remember to free the doubly linked list that
             * gtk_container_children() returns
             */
            dlist=gtk_container_children(GTK_CONTAINER(frame));
            free_list=dlist;
            while (dlist) {
                GtkWidget       *list_item;
                
                list_item=dlist->data;
                
                gtk_widget_reparent(list_item, gtklist);
                
                dlist=dlist->next;
            }
            g_list_free(free_list);
            
            /* if we have a new prisoner, remove him from the
             * GtkList and put him into the frame "Prison"
             * we need to unselect the item before
             */
            if (new_prisoner) {
                GList   static_dlist;
                
                static_dlist.data=new_prisoner;
                static_dlist.next=NULL;
                static_dlist.prev=NULL;
                
                gtk_list_unselect_child(GTK_LIST(gtklist),
                                        new_prisoner);
                gtk_widget_reparent(new_prisoner, frame);
            }
        }
    }

    /* this is the signal handler that gets called if GtkList
     * emits the "selection_changed" signal
     */
    void
    sigh_print_selection    (GtkWidget      *gtklist,
                             gpointer       func_data)
    {
        GList   *dlist;
        
        /* fetch the doubly linked list of selected items
         * of the GtkList, remember to treat this as read-only!
         */
        dlist=GTK_LIST(gtklist)->selection;
        
        /* if there are no selected items there is nothing more
         * to do than just telling the user so
         */
        if (!dlist) {
            g_print("Selection cleared\n");
            return;
        }
        /* ok, we got a selection and so we print it
         */
        g_print("The selection is a ");
        
        /* get the list item from the doubly linked list
         * and then query the data associated with list_item_data_key
         * we then just print it
         */
        while (dlist) {
            GtkObject       *list_item;
            gchar           *item_data_string;
            
            list_item=GTK_OBJECT(dlist->data);
            item_data_string=gtk_object_get_data(list_item,
                                                 list_item_data_key);
            g_print("%s ", item_data_string);
            
            dlist=dlist->next;
        }
        g_print("\n");
    }

12.4 List Item物件 

GtkListItem物件是设计用来做为container的子物件, 用来提供
selection/deselection的功能. 

GtkListItem有自己的视窗来接收事件并有其自身的背景颜色, 一般是白色的. 

因为是由GtkItem而来的, 它也可以用GTK_ITEM(ListItem)巨集. 一般
GtkListItem只有一个标签, 用来记录例如一个档名. 另外还有一个很好用的函
数gtk_list_item_new_with_label(). 若您不想加GtkLabel到GtkListItem, 也可
以加GtkVBox或GtkArrow. 

12.5 信号 

GtkListItem不产生自己的新的信号, 但它继承GtkItem的信号. 

12.6 函数 

    guint gtk_list_item_get_type (void)

返回`GtkListItem' type identifier. 

    GtkWidget* gtk_list_item_new (void)

产生新的`GtkListItem' object. 新物件返回一个指标给`GtkWidget'物件.
`NULL'表示错误. 

    GtkWidget* gtk_list_item_new_with_label (gchar *LABEL)

产生新的`GtkListItem'物件, 并带一个标签. 并返回一个`GtkWidget' object.
`NULL'表示错误. 

    void gtk_list_item_select (GtkListItem *LIST_ITEM)

这个函数基本上是将gtk_item_select (GTK_ITEM (list_item))包装起来. 它将
会送GtkItem::select信号. *Note GtkItem::, for more info. 

    void gtk_list_item_deselect (GtkListItem *LIST_ITEM)

这个函数基本上是将gtk_item_deselect (GTK_ITEM (list_item))包装起来. 它
将会送GtkItem::deselect信号. *Note GtkItem::, for more info. 

    GtkListItem* GTK_LIST_ITEM (gpointer OBJ)

传一个generic pointer到`GtkListItem*'. *Note Standard Macros::, for more
info. 

    GtkListItemClass* GTK_LIST_ITEM_CLASS (gpointer CLASS)

传一个generic pointer到`GtkListItemClass*'. *Note Standard Macros::, for
more info. 

    gint GTK_IS_LIST_ITEM (gpointer OBJ)

决定generic pointer是否对照到`GtkListItem' object. *Note Standard
Macros::, for more info. 

12.7 例子 

Please see the GtkList example on this, which covers the usage of a
GtkListItem as well. 


译注: List物件这一篇本身比较不容易翻译, 因原文本身讲的并不太清楚. 此外,
其结构原本就比较繁琐. 若您在此糟遇问题, 可来信反应. 译者会想办法将其改
善. 
If you got stuck here, it's mostly not your problem. Don't feel frustration. The
List Widget itself is pretty complicated. You may drop me a word if you need.
I will try to improve it. 

--
        6m3m┌───────────────────────┐0m
        6m3m│     4m疾如风,徐如林,侵掠如火,不动如山       3m│4m 0m
        6m3m└───────────────────────┘0m4m 0m
          4m                                                 0m

m;32m※ 来源:.华南网木棉站 bbs.gznet.edu.cn.[FROM: 202.38.212.66]m
--
m;32m※ 转寄:.华南网木棉站 bbs.gznet.edu.cn.[FROM: mtlab.hit.edu.cn]
--

                              Enjoy Linux!
                          -----It's FREE!-----

※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: mtlab.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:209.434毫秒