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开发指南