GTK之treeview的学习
其实接触gtk也没多久,只是把学到的做一总结,也算是备忘吧,以后真要忘了的话【几乎是铁定的了】,翻着看看,还能想起来。
感觉treeview控件对于gtk的入门来说应该算比较高级的构件了,而且学习它的同时也可以学习下gtk+是如何实现MVC架构的。
说起MVC,现在应该还算比较流行的了。其实也就是model-view-controller,就其本身而言,其实好像也没多大新意。Gtk+对其的实现不是很标准,但应该说有些东西还是套用的,因为本身差别并不大。
以treeview的使用为例,
首先我们定义model
GtkTreeModel *list_model_create()
{
GtkListStore *store;
store = gtk_list_store_new(3,G_TYPE_STRING, G_TYPE_STRING,G_TYPE_STRING);
return GTK_TREE_MODEL(store);
}
当然这里面先不加载具体的数据。Gtk中用于treeview的model一般可以用liststore或treestore来实现。
然后,将view与model关联起来
Code
void list_view_ini(GtkWidget *list)
{
GtkCellRenderer *renderer_icon,*renderer_text;
GtkTreeViewColumn *column;
renderer_icon = gtk_cell_renderer_pixbuf_new();
renderer_text = gtk_cell_renderer_text_new();
column=gtk_tree_view_column_new ();
gtk_tree_view_column_set_title(column,"hello world");
gtk_tree_view_column_pack_start(column,renderer_icon,FALSE);
gtk_tree_view_column_pack_start(column,renderer_text,FALSE); gtk_tree_view_column_add_attribute(column,renderer_icon,"stock-id",0); gtk_tree_view_column_add_attribute(column,renderer_text,"text",1);
gtk_tree_view_column_add_attribute(column,renderer_text,"foreground",2);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
}
看起来比较复杂,其实还是比较简单的
首先view要通过column来展现,而column中的内容,则有store来提供,当然store并不管里面具体是什么东西,所以,就需要cellrenderer来描述。而具体的数据可能又有很多行(row),每一行怎么区别呢,就要用到iter。
当然上面的实现还是复杂了些,因为每个列有两个cellrenderer(一个用来描述图标,另一个用来描述文字),如果每一个列(column)只有一种属性,或是文本,或是图片,那就可以用更方便的使用如下函数。
column = gtk_tree_view_column_new_with_attributes("column 1",renderer_icon, "stock-id", 0, NULL);
gtk_list_view_append_column(GTK_TREE_VIEW(list), column);
这样就简单多了。
至此我们就建立了model和view,当然具体的数据还没有添加。
在添加具体数据之前,先看看在main函数中应如何调用
GtkWidget *list;
list= gtk_tree_view_new_with_model(list_model_create());
list_view_ini(list);
下面要往里面填数据了,
Code
void list_append(GtkWidget *list, const gchar *icon,const gchar *str,const gchar *col)
{
GtkListStore *store;
GtkTreeIter iter;
store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0,icon,1, str,2,col, -1);
}
我们定义了一个插入用的函数,传入的后三个参数icon,str,col分别表示图标,文自信息和文字信息对应的颜色,图标对应的cellrenderer是pixbuf型的,而文字信息及其颜色是一个text型cellrenderer的两个属性,前面通过pack打包到一个column里面了。
在main函数中,只需简单的插入数据就行了,例如
list_append(list,GTK_STOCK_CLOSE,"hello","grey");
list_append(list,GTK_STOCK_CLOSE,"world","grey");
treeview已经构建完成了,但这似乎没有什么用啊,要真正有用还需要知道如何获取选择信息,
当然首先要做一信号的链接model=gtk_tree_view_get_model(GTK_TREE_VIEW(list));
g_signal_connect(selection, "changed", G_CALLBACK(on_changed), model);
这里将model传入是为了实现一个简单的图标变化。当然还需额外说明的是菜单的选择还需要使用到一个名为selection的构件,它是专门用来描述treeview的选择项的
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
选择项若有所改变其相应的回调函式如下,
void on_changed(GtkWidget *widget, GtkTreeModel *model)
{
GtkTreeIter iter;
char *value;
gtk_tree_model_get_iter_from_string (model, &iter, "0");
if(gtk_tree_selection_iter_is_selected(GTK_TREE_SELECTION(widget),&iter))
{
gtk_list_store_set(GTK_LIST_STORE(model),&iter,LIST_ICON,GTK_STOCK_APPLY,LIST_COLOR,"green",-1);
gtk_tree_model_get_iter_from_string (model, &iter, "1");
gtk_list_store_set(GTK_LIST_STORE(model),&iter,LIST_ICON,GTK_STOCK_CLOSE,LIST_COLOR,"red",-1);
}
else
{
gtk_list_store_set(GTK_LIST_STORE(model),&iter,LIST_ICON,GTK_STOCK_CLOSE,LIST_COLOR,"red",-1);
gtk_tree_model_get_iter_from_string (model, &iter, "1"); gtk_list_store_set(GTK_LIST_STORE(model),&iter,LIST_ICON,GTK_STOCK_APPLY,LIST_COLOR,"green",-1);
}
}
这里面的方法还是比较麻烦的逐一判断的那种,这主要是为了能够实现对图标的选择性修改,当然一般来说如果只需要获取选择信息可以用一种很简单的方式。
Code
void on_changed(GtkWidget *widget, gpointer data)
{
GtkTreeIter iter;
GtkTreeModel *model;
char *value;
if (gtk_tree_selection_get_selected(
GTK_TREE_SELECTION(widget), &model, &iter))
{
gtk_tree_model_get(model, &iter, LIST_ITEM, &value, -1);
g_free(value);
}
}
这里要注意获取的value实则指向了一块新分配在自由存储区的内存,用完要及时释放掉。
至此,就完成了的一个简单的treeview小程序。
下面贴出完整的代码,
Code
1 #include <gtk/gtk.h>
2
3 enum
4 {
5 LIST_ICON=0,
6 LIST_TEXT ,
7 LIST_COLOR,
8 N_COLUMNS
9 };
10
11 GtkTreeModel *list_model_create()
12 {
13
14 GtkListStore *store;
15 store = gtk_list_store_new(N_COLUMNS,G_TYPE_STRING, G_TYPE_STRING,G_TYPE_STRING);
16 return GTK_TREE_MODEL(store);
17 }
18 void list_view_ini(GtkWidget *list)
19 {
20 GtkCellRenderer *renderer_icon,*renderer_text;
21 GtkTreeViewColumn *column;
22 renderer_icon = gtk_cell_renderer_pixbuf_new();
23 renderer_text = gtk_cell_renderer_text_new();
24
25 column=gtk_tree_view_column_new ();
26 gtk_tree_view_column_set_title(column,"hello world");
27 gtk_tree_view_column_pack_start(column,renderer_icon,FALSE);
28 gtk_tree_view_column_pack_start(column,renderer_text,FALSE);
29 gtk_tree_view_column_add_attribute(column,renderer_icon,"stock-id",LIST_ICON);
30 gtk_tree_view_column_add_attribute(column,renderer_text,"text",LIST_TEXT);
31 gtk_tree_view_column_add_attribute(column,renderer_text,"foreground",LIST_COLOR);
32 gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
33 }
34 void list_append(GtkWidget *list, const gchar *icon,const gchar *str,const gchar *col)
35 {
36 GtkListStore *store;
37 GtkTreeIter iter;
38
39 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
40
41 gtk_list_store_append(store, &iter);
42 gtk_list_store_set(store, &iter, LIST_ICON,icon,LIST_TEXT, str,LIST_COLOR,col, -1);
43
44 }
45
46 void on_changed(GtkWidget *widget, GtkTreeModel *model)
47 {
48 GtkTreeIter iter;
49
50 char *value;
51
52 gtk_tree_model_get_iter_from_string (model, &iter, "0");
53 if (gtk_tree_selection_iter_is_selected(GTK_TREE_SELECTION(widget),&iter))
54 {
55 gtk_list_store_set(GTK_LIST_STORE(model),&iter,LIST_ICON,GTK_STOCK_APPLY,LIST_COLOR,"green",-1);
56 gtk_tree_model_get_iter_from_string (model, &iter, "1");
57 gtk_list_store_set(GTK_LIST_STORE(model),&iter,LIST_ICON,GTK_STOCK_CLOSE,LIST_COLOR,"red",-1);
58
59 }
60 else
61 {
62 gtk_list_store_set(GTK_LIST_STORE(model),&iter,LIST_ICON,GTK_STOCK_CLOSE,LIST_COLOR,"red",-1);
63 gtk_tree_model_get_iter_from_string (model, &iter, "1");
64 gtk_list_store_set(GTK_LIST_STORE(model),&iter,LIST_ICON,GTK_STOCK_APPLY,LIST_COLOR,"green",-1);
65
66 }
67
68 }
69 int main (int argc, char *argv[])
70 {
71 GtkWidget *window;
72
73 GtkWidget *list;
74 GtkWidget *vbox;
75 GtkTreeModel *model;
76 GtkTreeSelection *selection;
77 gtk_init(&argc, &argv);
78
79 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
80 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
81 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
82 gtk_widget_set_size_request(window, 270, 250);
83 gtk_window_set_title(GTK_WINDOW(window), "list View");
84
85
86 vbox = gtk_vbox_new(FALSE, 0);
87 list= gtk_tree_view_new_with_model(list_model_create());
88
89 gtk_box_pack_start(GTK_BOX(vbox), list, TRUE, TRUE, 5);
90 gtk_container_add(GTK_CONTAINER(window), vbox);
91
92 list_view_ini(list);
93 list_append(list,GTK_STOCK_CLOSE,"hello","grey");
94 list_append(list,GTK_STOCK_CLOSE,"world","grey");
95
96 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
97 gtk_tree_selection_set_mode(selection,GTK_SELECTION_SINGLE);
98 model=gtk_tree_view_get_model(GTK_TREE_VIEW(list));
99 g_signal_connect(selection, "changed", G_CALLBACK(on_changed), model);
100 g_signal_connect(G_OBJECT (window), "destroy",G_CALLBACK(gtk_main_quit), NULL);
101 gtk_widget_show_all(window);
102 gtk_main ();
103 return 0;
104 }
阅读(1794) | 评论(0) | 转发(0) |