在Gtk+中使用流式布局
搞Gtk的大牛们搞什么飞机哦,布局Widget这样的东西,居然被大牛们当成MM一样藏起来拉!就藏在GIMP里面作Custom Widget也不放到GTK作为标准控件。
做一个小玩意时我遇到了一个比较令人苦恼的问题,那就是Gtk+ 的布局管理Widget里面没有那种像Java Flowlayout一样的东西。什么box,什么frame,都不是我想要的。
记得学java布局管理的时候觉得流式布局真白痴,其实也有可用之处啊,最典型的就是GIMP和Dia这样的toolbox啦,就像下面这样,在WIndows的UI系统里面搞这个不是那么容易的吧…

Dia toolbox
我在Gtk的参考里面找啊找,还是没找到,于是去看Dia的源代码去。
NNNNND!我我居然发现了一个叫GtkWrapBox的Widget。NNND,去google一看,还真有这个玩意,就在Gimp的在线Gtk接口文档中。
可以看到这个叫GtkWrapBox的Widget有两个派生,分别是横向折行和纵向折行;可以看到这个叫GtkWrapBox的Widget还是GtkContainer的派生类;但是最可恶的地方就是——你去看文档里面的Object Hierarchy吧,GtkContainer下绝对没有GtkWrapBox,GtkWrapBox的上层Object绝对是 GtkContainer。NND。
http://developer.gimp.org/api/2.0/app/GtkWrapBox.html#id3166842
http://developer.gimp.org/api/2.0/gtk/GtkContainer.html#id3824858
搞Gtk的大牛们搞什么飞机哦,布局Widget这样的东西,居然被大牛们当成MM一样藏起来拉!就藏在GIMP里面作Custom Widget也不放到GTK作为标准控件。
好了,既然这样就好办了。我去把GtkWrapBox的源码搞过来看一下就好了。源码如下:
$ ls *.c *.h
gtkhwrapbox.c gtkvwrapbox.c gtkwrapbox.c
gtkhwrapbox.h gtkvwrapbox.h gtkwrapbox.h
下面我来测试一下下啦。我拿GTK 的Hello World改了一段代码,可用!
[main.c]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #include <gtk/gtk.h> #include <gtk/gtk.h> #include <gtk/gtkcontainer.h> #include "gtkhwrapbox.h" /* This is a callback function. The data arguments are ignored * in this example. More on callbacks below. */ static void hello( GtkWidget *widget, gpointer data ) { g_print ("Hello World\n"); } static gboolean delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { /* If you return FALSE in the "delete_event" signal handler, * GTK will emit the "destroy" signal. Returning TRUE means * you don't want the window to be destroyed. * This is useful for popping up 'are you sure you want to quit?' * type dialogs. */ g_print ("delete event occurred\n"); /* Change TRUE to FALSE and the main window will be destroyed with * a "delete_event". */ return TRUE; } /* Another callback */ static void destroy( GtkWidget *widget, gpointer data ) { gtk_main_quit (); } int main( int argc, char *argv[] ) { /* GtkWidget is the storage type for widgets */ GtkWidget *window; GtkWidget *button[10]; /* This is called in all GTK applications. Arguments are parsed * from the command line and are returned to the application. */ gtk_init (&argc, &argv); /* create a new window */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); //给windows连接delete_event信号 g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); //给windows连接destroy信号 g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); //设置边框 gtk_container_set_border_width (GTK_CONTAINER (window), 10); // 创建一个 hwrapbox GtkWidget * wrapbox = gtk_hwrap_box_new(FALSE); /* 创建 10 个 button with the label "Fuck Off". */ int i = 0; for (i = 0; i < 10; ++i) { button[i] = gtk_button_new_with_label ("Fuck Off"); //将clicked信号连接到hello函数 g_signal_connect (G_OBJECT (button[i]), "clicked", G_CALLBACK (hello), NULL); //将clicked信号连接到gtk_widget_destroy, 考虑到该 //函数接受一个widget参数, So, 使用g_signal_connect_swapped g_signal_connect_swapped (G_OBJECT (button[i]), "clicked", G_CALLBACK (gtk_widget_destroy), G_OBJECT (window)); //将各个button打包进wrapbox gtk_wrap_box_pack(GTK_WRAP_BOX(wrapbox), button[i], FALSE, FALSE, FALSE, FALSE); //显示各个button gtk_widget_show (button[i]); } //把wrapbox加入window gtk_container_add (GTK_CONTAINER (window), wrapbox); // 显示wrapbox和windows. gtk_widget_show (wrapbox); gtk_widget_show (window); //gtk main入口函数 gtk_main (); return 0; } |
这里是我用的makefile:
[makefile]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | GLADE_ADD = -export-dynamic -Wall LINKFLAGS = `pkg-config --libs gtk+-2.0 libglade-2.0` $(GLADE_ADD) CFLAGS = `pkg-config --cflags gtk+-2.0 libglade-2.0` $(GLADE_ADD) OBJ = main.o gtkhwrapbox.o gtkvwrapbox.o gtkwrapbox.o main: $(OBJ) gcc -o main $(OBJ) $(LINKFLAGS) %.o: %.c gcc -g -c $(CFLAGS) $< -o $@ clean: rm -f *.o main |
下面是screenshot, 还是可以的啦 , 不过嗯个,还有个问题,因为这个玩意不属于gtk标准组件,所以pygtk里面也没有它啦,那…岂不是要我自己搞一下 (ToT)。
Tags: flowlayout, gtk, layout, linux, programming, 布局, 流式布局

















July 20th, 2008 at 3:17 pm
哇!这么好的文章。现在才看到,Feedsky真的出问题了!
[Reply(回复)]
July 20th, 2008 at 3:21 pm
[quote comment="216"]哇!这么好的文章。现在才看到,Feedsky真的出问题了![/quote]
呵呵,这不是TX同学嘛。过奖过奖。你的到来让我的小博蓬荜生辉哈。
[Reply(回复)]
July 20th, 2008 at 7:17 pm
-_-#
“蓬荜生辉”。。。这么夸张~那我每天都来逛了!
另外,我在想,GTK+-3.0估计会引入很多GIMP里的东西,比如你这篇文章中写的。
GIMP的大牛们喜欢把好东西藏着偷偷用,呵呵!
[Reply(回复)]
July 20th, 2008 at 9:38 pm
[quote comment="218"]-_-#
“蓬荜生辉”。。。这么夸张~那我每天都来逛了!
另外,我在想,GTK+-3.0估计会引入很多GIMP里的东西,比如你这篇文章中写的。
GIMP的大牛们喜欢把好东西藏着偷偷用,呵呵![/quote]
我在想移植工作会不会很难…呵呵。gtk 3确实令人期待
[Reply(回复)]
July 21st, 2008 at 8:50 pm
GtkWrapbox.py
可以看这里 http://paste.ubuntu.org.cn/8327
[Reply(回复)]
July 21st, 2008 at 9:17 pm
a[quote comment="224"]GtkWrapbox.py
可以看这里 http://paste.ubuntu.org.cn/8327/quote
啊,非常感谢。
[Reply(回复)]
July 21st, 2008 at 10:06 pm
山猫给的东西真好!
Python版的是继承于gtk.Table的啊,好好去研究一下。
[Reply(回复)]
July 21st, 2008 at 10:39 pm
[quote comment="228"]山猫给的东西真好!
Python版的是继承于gtk.Table的啊,好好去研究一下。[/quote]
山猫具体是谁哈?
这个pyGtkWrapBox基本满足需求
[Reply(回复)]
July 22nd, 2008 at 8:05 pm
[quote comment="228"]Python版的是继承于gtk.Table的啊,好好去研究一下。[/quote]
嗯,这个就是用来弄类似 gimp 工具面板按钮的。
猫猫和 TualatriX
有空也来改进下 glade2py 吧
http://paste.ubuntu.org.cn/8340
从 glade-3 xml 文件生成 pyGtk 代码
我添加了 gtk.HandleBox 支持,
不过还缺
gtk.Toolbar
和
gtk.ToolbarSpaceStyle
gtk.ToolButton
gtk.ToolbarChildType
gtk.ToolbarStyle
gtk.ToolItem
[Reply(回复)]
July 22nd, 2008 at 8:17 pm
PyGtk 里还有个更懒的邪恶方式做流式布局,
用 gtk.TextView 或 gtkhtml2 做容器,
将控件插进去,
由 gtk.TextView 或 gtkhtml2 来处理布局。
这个 GtkLinkTextView 插按钮或文字链接比 TextView 要方便些
http://paste.ubuntu.org.cn/8369
[Reply(回复)]
July 22nd, 2008 at 8:34 pm
对了,猫猫 加个新评论邮件通知插件吧
[Reply(回复)]
July 22nd, 2008 at 9:46 pm
呜~能碰到一块做Pygtk的朋友真是好难得啊。
山猫一般都在哪里泡坛子?怎么ShelleX叫猫猫?呵呵!
[Reply(回复)]
July 22nd, 2008 at 10:05 pm
[quote comment="237"]呜~能碰到一块做Pygtk的朋友真是好难得啊。
山猫一般都在哪里泡坛子?怎么ShelleX叫猫猫?呵呵![/quote]
他在Ubuntu中文论坛咯。因为我的头像是一只猫咪。所以叫我猫猫。
[Reply(回复)]
July 22nd, 2008 at 10:06 pm
[quote comment="236"]对了,猫猫 加个新评论邮件通知插件吧[/quote]
好像没有效果ye。我的py和gtk都是初学的说。
[Reply(回复)]
July 22nd, 2008 at 11:50 pm
[quote comment="240"][quote comment="236"]对了,猫猫 加个新评论邮件通知插件吧[/quote]
好像没有效果ye。我的py和gtk都是初学的说。[/quote] 需要配置 sendmail 或 smtp,
选 sendmail 的话,可以用 msmtp-mta 之类
[Reply(回复)]
July 23rd, 2008 at 1:36 pm
[quote comment="247"][quote comment="240"][quote comment="236"]对了,猫猫 加个新评论邮件通知插件吧[/quote]
好像没有效果ye。我的py和gtk都是初学的说。[/quote] 需要配置 sendmail 或 smtp,
选 sendmail 的话,可以用 msmtp-mta 之类[/quote]
已经搞定了,:)
这个是sendmail,Linux主机的说
[Reply(回复)]
July 23rd, 2008 at 9:34 pm
[quote comment="248"]已经搞定了,:)
这个是sendmail,Linux主机的说[/quote]
赞,虽然邮件标题有些乱码
[quote]date Wed, Jul 23, 2008 at 1:36 PM
subject [ShelleX is Not ShelleXtend] New Comment On: 在Gtk+���使用流式布局[/quote]
对了, msmtp-mta 是一个利用其他 smtp 账号发信的 sendmail, 而不是 “ms 的 mta”
[Reply(回复)]
July 23rd, 2008 at 10:01 pm
[quote comment="251"][quote comment="248"]已经搞定了,:)
这个是sendmail,Linux主机的说[/quote]
赞,虽然邮件标题有些乱码
[quote]date Wed, Jul 23, 2008 at 1:36 PM
subject [ShelleX is Not ShelleXtend] New Comment On: 在Gtk+���使用流式布局[/quote]
对了, msmtp-mta 是一个利用其他 smtp 账号发信的 sendmail, 而不是 “ms 的 mta” :)[/quote]
哦,,,,这样子哈,知道了。谢谢
[Reply(回复)]
December 23rd, 2008 at 3:40 pm
你也成大牛了阿
[Reply(回复)]