Glade 3与GTK+-2入门
本文是用GTK和MySQL完成学生信息管理系统的第一部分
GTK是完全按照面向对象思想设计的一套组件,如果你用过java的Swing那就应该会很容易的理解这个东西。按我现在的水平,我只当GTK就是些图形组件。Glade是可以让你用拖拽的方式来给GTK这些组件进行布局的,用过Netbeans进行Swing设计的应该会明白,当然如果你用过垃圾的VC(ABitNo坚决讨厌这些东西)什么的也会明白。不过不明白也没关系,下面就一切从0开始讲解。
现在ABitNo假设读者会用c,gcc,make。不过不会的话还是没有关系,下面会把每一步需要的命令都列出来。
1、准备开发环境
Linux,GTK+-2,Glade 3.6,gcc,make,Glib2,MySQL
上面这些东西并不是现在就都会用到,是以后的文章中会用到的。由于这些都不是重点,所以就不详细介绍了,如有不明白的就留言,ABitNo愿意帮忙。
2、认识Glade
当你打开Glade3时,会出现一个Unsaved 1的对话框,这个是让你选择现在这个Project的一些基本属性。这里就按照默认的,不要修改。
我们来认识下你看到的Glade窗口,最上面是菜单栏,菜单栏下面的是工具栏;左边那列叫Palette,你所需要的组件都在那里了;中间那个最大的白色空间是你的工作区;右边上部的白色部分叫Inspector,是你添加的组件的一个导航列表;右边下部是Properties,当你点击了某个组件后,在这里会出现它的属性,你可以对它们进行编辑。
3、设计界面
这个应该就不困难了,就是点击Palette里的组件,然后摆放位置,调节属性。如果你不明白应该如何去做,那就按照我给出的这个小示例来一步步走。
- 在Palette里点击Toplevels下的window组件,这时在中间的空白工作区会出现一个深色方框,这个就是你程序的主窗口。
- 在Inspector里,用鼠标选中你刚新建的那个窗口,在下面的Properties里进行如下编辑:
- General标签下,将Name属性改为window,将Window Title改为ABitNo;
- 在Signals标签下,你可以在GtkWidget那一类中找到个delete-event,为它的Handler选择gtk_main_quit,同样给GtkObject那一类中唯一的destroy选择gtk_main_quit
- 在Palette里点击Container下的Fixed,在你上一步新建的window中点击,这样就创建好了一个容器,然后按照给window修改名字的方法将其改名为fixed。容器就是一个可以存放其他组件并进行布局的一种组件
- 在Palette里点击Control and Display下的Label,在Fixed容器上点击,这样你就把label放到了Fixed容器里了,在Properties的General标签下将Name属性改为label,将Label属性里的内容都删除。最后你可以点击工具栏上的那个Drag Resize按钮,然后你就可以选中label进行拖拽,来摆放出一个合适的位置,位置不会影响程序的功能,但是会影响美观(ABitNo做的就很不美观)
- 在Palette里点击Control and Display下的Button,在Fixed容器上点击,这样你就在Fixed容器里又放置了一个按钮,将其Name属性改为button,Label属性改为ABitNo,同样的你可以通过拖拽来调节它的大小和位置
这样我们的界面就设置完成了,保存为abitno.glade。最后的设计和Inspector里的内容会像下面这样
4、编写代码
这一步才是关键,界面设计是次要的,Glade就是把界面与代码分开,这样更便于维护。先不多说了,直接看代码,代码里ABitNo都已经把注释写的很详细了,如果仍然有不明白的可以提出来。
你现在要做的就是打开一个编辑器,如gedit,在abitno.glade所在的文件夹里编辑一个文件abitno.c,内容如下
/* * File :abitno.c * Author: ABitNo * Email: wolfplanet@gmail.com * Website: ABitNo.LinPie.com */ /*********************************************************************** * 这句include就是简单的包含gtk的头文件 * ***********************************************************************/ #include <gtk/gtk.h> /*********************************************************************** * 从名字就可以看出这是一个button被点击时要执行的函数 * ***********************************************************************/ void on_button_clicked(GtkWidget *widget, gpointer label) { /*这是gtk的一个函数,用来给Label设定文字*/ gtk_label_set_text(GTK_LABEL(label),"I Love ABitNo.LinPie.com"); } int main(int argc, char *argv[]) { /*这些語句声明了一些组件变量,由于GTK是面向对象的, 所以都可以声明为GtkWidget,这也是习惯作法 */ GtkBuilder *builder; GtkWidget *window; GtkWidget *button; GtkWidget *label; /*每一个gtk程序都会用到这一句,用来初始化*/ gtk_init(&argc, &argv); /*这个builder就是用来读取我们用Glade设计的界面的一个东西*/ builder = gtk_builder_new(); /*用下面这个gtk函数把abitno.glade的内容给builder*/ gtk_builder_add_from_file(builder, "abitno.glade", NULL); /*通过名字从abitno.glade中读取我们需要使用的组件*/ window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); button=GTK_WIDGET(gtk_builder_get_object(builder,"button")); label=GTK_WIDGET(gtk_builder_get_object(builder,"label")); /*这是glib里的一个函数,用来把一个组件与一个函数关联起来,下面 这句就是把button和我们上面的那个on_button_clicked给关联了*/ g_signal_connect( G_OBJECT(button), "clicked", G_CALLBACK(on_button_clicked), (gpointer)label); /*这条語句就是自动把所有人信号处理函数都关联好*/ gtk_builder_connect_signals(builder, NULL); /*因为我们已经不需要builder了,就释放builder的空间*/ g_object_unref(G_OBJECT(builder)); /*将window内所有的组件都显示出来,这们我们才能看见*/ gtk_widget_show_all(window); /*这也是每一个gtk程序都要有的*/ gtk_main(); return 0; }
5、编译运行
当你的代码都写完了,那就保存,准备编译了,用下面的命令
gcc -o abitno abitno.c `pkg-config --cflags --libs gtk+-2.0` -export-dynamic
要注意,pkg-config前后的那个不是单引号,而是ESC下面那个键。
然后通过下面的命令来运行
./abitno
如果一切顺利的话,就会出现一个窗口,上面只显示一个ABitNo按钮,你点击它就会出现一句话“I Love ABitNo.LinPie.com“,如下图
本文基于 署名-非商业性使用-禁止演绎 2.5 中国大陆 发布
46 COMMENTS >>LEAVE<<
-
不错!
-
@gcell
谢谢,ABitNo会感激你的。。。ABitNo会继续努力的。。。
-
不错的文章。国内关于GTK和Glade 3的文章太少了,没有地方学习,以后会常来看看的。
-
@xbox
谢谢关注。ABitNo会努力的。。。
-
文章很好,我会多多关注!
-
恩,不错!现在glade文章确实少。
-
@nix
谢谢,我会多多努力。。。
-
@Xhacker
是的,而且都还比较旧,估计用的人不是很多吧。。。那些大牛估计会习惯写代码,刚开始学的说不定还不知道这个东西呢。。。
-
使用fixed layout是windows遗留思想
-
@Feng
那倒不是,我还真没Windows过。。。主要的问题是我不会用GTK,我要好好学习才行。。。
-
教程么,http://www.zetcode.com/ 这个网站里面有很多教程
-
@AzureSky
对,就是那,我就在那学了很多。。。
-
我真会YY, 东西是这样命名的xx-clothes-bra
-
@邱焜
不明白是什么意思。。。
-
那首歌叫什么名字?
-
@海贼阿D
阿沁的那个南极星。。。里面那女声真好听。。。
-
这两天也在看Glade, 带着看点gtkmm,主要是觉得用C写Gtk界面太痛苦了,函数名老长,还要加各种宏,各种box,加得自己都乱了。添加一个widget、设定属性、连接回掉函数、添加到某个box,然后show(), 程序代码基本没法看。
-
@JackalDire
我也是这么觉得,我觉得C语言就没法看,用起来也痛苦,C++东西就太多了,我也不想学了,还是学我的Ruby和Java,C语言还是一定要学的,虽然让我很痛苦
-
请问楼主,gtk_builder_add_from_file是动态加载吧?就是说.glade文件要和程序放在一起的吧?那样的话,界面不就不保密了?只要得到你的软件包,用同样方式加载你的.glade,改下callback,不就直接用你的界面了?
我在网上搜的方法都是这样(来到你在这也要谢谢GOOGLE),不过听说有种静态加载方式,请问你知道吗?
还有,你写GTK的代码,用vi还是什么?能自动提示吗?我在windows或者linux下,gtk的自动提示不能解决,很是头疼,健忘的我尤其痛苦
-
@ExclusivePig
是的,上面说的是动态加载的,要把glade文件和程序放到一起。
至于要静态加载,我也没考虑过,不过肯定是会有这种方法的。我这个暑假要好好学Linux编程,现在还只是大体了解,等我知道了,一定会告诉你,大家一起学习。。。
写GTK的用vi就行,可以自动提示的,当然还可以用一些ide,不过这些都是默认不扫描gtk的东西的,都要自己配置一下,我只会设置vi和netbeans的,其实这样设置了提示也不好,gtk的东西实在是太多了,那么长的提示列表。。。
gtk的命名也很规律的,只要大体明白是个什么就能記住了。。。
我现在不是很在行,过了这个假期或许我会比现在知道的更多。。。
-
glade很多地方都是用GladeXML获得界面的,但是的 我用的时候会加载失败,不知道为什么
然后我用你这里的这种方法的话,每个控件的消息响
应都要自己去g_signal_connect么?除非是系统自
带的函数么? -
@graint
不是每个都用的,你可以直接在做设计的时候就关联好,然后
gtk_builder_connect_signals
就能把所有你在设计中关联的东西自己关联的
不过我现在对这些还不是很了解,主要是很长时间没看了,这个暑假后会好一点,我会专心学习Linux编程的。。。
谢谢你的关注
-
@ABitNo
在glade中消息响应函数,比如一个BUTTON,我设置响应clicked消息的函数叫on_button1_clicked,然后在C文件里声明这个函数,但是在gtk_builder_connect_signals的时候仍然说on_button1_clicked不存在,那设置的函数名应该怎么用啊
-
@graint
这个我刚刚又自己写了个简单的小例子看了下,发现是没有问题的,看看今晚我有没有时间,你把你的文件发给我,我看一下呢。。。
-
@ABitNo
是我编译的时候少加了个参数。。我的错
我发现gtk_builder_get_object这样拿出来的控件不能直接显示之类的?
比如我拿出一个image,然后在对一个button进行点击的时候把image作为参数传给button的响应函数,然后调用gtk_widget_hide,然后程序就崩了。。或者我在gtk_widget_show_all后面直接对image进行gtk_widget_hide操作,仍然没有任何效果啊
-
@graint
graint says:
2009/07/28 at 16:45 (Edit)是我编译的时候少加了个参数。。我的错
我发现gtk_builder_get_object这样拿出来的控件不能直接显示之类的?
比如我拿出一个image,然后在对一个button进行点击的时候把image作为参数传给button的响应函数,然后调用gtk_widget_hide,然后程序就崩了。。或者我在gtk_widget_show_all后面直接对image进行gtk_widget_hide操作,仍然没有任何效果啊
这个我也接着试验了一下,发现是可以的,你仔细看看是不是写错了名字还是什么的,C语言的细节问题要细心的。。。
-
@ABitNo
老大有没QQ之类即时聊天的。。~很希望能直接请教一下。。
-
@ABitNo
我QQ262009627 老大加下指导指导。。感激不尽呃
-
@graint
我没有QQ,看不起腾讯这种企业。。。
Gtalk: wolfplanet@gmail.com
MSN : wolfplanet@live.cn先去吃饭去了。。。
话说我现在对这些东西都忘了,刚做完那些项目,正准备再好好学一下。。。
-
用gtk_builder_connect_signals 的时候编译的时候必须加上
gccgtk x.c -Wl,--export-dynamic这样就行了
不过如果在glade里面传递user_data 注意callback函数 第一个参数才是user_datagccgtk是我用的一个别名 gccgtk=gcc 'pkg-config --cflags --libs gtk+2.0'后面还有一堆
要不让每次测试简单的程序写make麻烦了 打命令又要加一堆pkg-config
要保密 我觉得没必要。。。不过如果应要 就把glade文件写在代码里面当作一个
const char* 就是了 然后用gtk_builder_add_from_string -
@snyh
非常感谢,以后多向你学习了。。。
-
感谢楼主,找了很久终于找到好文。
不然还不知道怎么使用glade,希望楼主继续造福我们这些菜鸟。
多谢了! -
@崇拜
多谢夸奖。。。
我也是刚学习一点 -
那个用glade可以直接生成GUI的框架代码吧?
-
我也是极度讨厌vc,完全搞不明白那东西在搞毛阿,但是gtk+ 很可爱,很容易学习理解
-
@ReeChou
真抱歉,最近忙得没时间回复留言。。。
glade只是生成了界面,应该就是你所说的GUI的框架代码吧 -
@轩痕
哈哈,对,我一直在期待着gtk3呢,到时候一定好好研究一下
-
我运行之后程序不能正常运行,提示:
GTK-CRITICAL**:gtk_widget_show_all: assertion `GTK_IS_WIDGET(widget)` failed.
我调试了一下,发现window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));这一语句没有正确获得window,其他的widge也是如此。不知道为什么。 -
@joeguan2
你的glade文件里window的名字是不是window啊~~~
你要注意名字一致 -
@ABitNo
the names are identical.
the following codes are from .c file and .glade file.
/* gui.c */
#include <gtk></gtk>int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "gui.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
gtk_builder_connect_signals(builder, NULL);
g_object_unref(G_OBJECT(builder));
gtk_widget_show_all(window);
gtk_main();
return 0;
}
/* gui.glade */
<property name="title" translatable="yes">glade window</property><signal name="delete_event" handler="gtk_main_quit"></signal>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--Generated with glade3 3.4.3 on Wed Mar 10 16:42:23 2010 -->
<glade-interface><br><widget class="GtkWindow" id="window"><br></widget></glade-interface>
<child><br><placeholder></placeholder><p></p></child>
-
@ABitNo
两个文件的window是一致的,上一个回复不能显示gui.glade的代码。
-
@ABitNo
我出现了和joeguan2 一样的问题 我是大一的不懂怎么解决 能帮帮我吗? 我有的是window的系统 不是linux的 这有关系吗? 还有你先得glade教程真的很通俗 我找了好久终于找到这篇经典的了
-
按照你的例子做了下,编译完后运行程序报错内容如下:
(abitno:28984): GLib-GObject-WARNING **: invalid (NULL) pointr instance(abitno:28984): GLib-GObject-CRITICAL **: g_signal_connect_daa: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed
(abitno:28984): Gtk-CRITICAL **: gtk_widget_show_all: assertin `GTK_IS_WIDGET (widget)' failed
这是怎么回事?