当前位置:Linux教程 - Linux - GTK入门导读(List物件)

GTK入门导读(List物件)



         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
    #include

    /* 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.
    发布人:netbull 来自:Linux开发指南