Glade3+tutorial.docx
《Glade3+tutorial.docx》由会员分享,可在线阅读,更多相关《Glade3+tutorial.docx(31页珍藏版)》请在冰豆网上搜索。
Glade3+tutorial
GTK+andGlade3GUIProgrammingTutorial-Part1
2009年3月27日
23:
38
原文地址链接
作者Micah
Carrick
翻译:
Binn.X
Wee
博客链接:
本文链接:
QuickOverviewofGTK+Concepts
如果你没有任何GTK+的编程经验,那么,对于我将要阐述的一些概念你也许会听着犯迷
糊。
不过,不用担心,在遇到这些概念的时候我会详细讲解,以便你能很好的阅读后面
的内容。
学完这一部分,对GTK+的基本概念有所了解后,你也许就能有效的利用Glade
进行开发了。
首先,GTK+并不是一门编程语言,而是一个开发工具套件,或者说是一个开发库,用
来进行跨平台GUI应用程序的开发,Linux,OSX,Windows或其它任何平台都能使用
GTK+。
GTK+就好比Windows上的MFC和Win32
API,JAVA上的Swing和SWT,或者
Qt(KDE使用的Linux下GUI开发套件)。
尽管GTK+是用纯C语言编写的,但是提供了其它各种语言的捆绑,允许程序员选择自己
喜欢的开发语言来开发GTK+应用程序,比如C++,
Python,Perl,PHP,Ruby等等。
GTK+开发套件基于三个主要的库:
Glib,Pango,和ATK,当然我们只需关心如何使用
GTK+即可,GTK+自己负责与这三个库打交道。
Glib封装了大部分可移植的C库函数
(允许你的代码移植到Windows和Linux上运行)。
使用C或C++时,将大量使用Glib库
函数,在我们用C语言的具体实现过程中我会详细解释它们。
高级语言如Python和Ruby
却不用担心Glib的使用,因为它们有自己的标准库提供了相应的功能。
GTK+及相关的库时按照面向对象设计思想来实现的,至于这时如何实现的现在并不重
要,不同的编程语言有不同的实现方法,重要的是要知道GTK+使用面向对象编程技术
即可(是的,即使是C实现的)。
每一个GTK+的GUI元素都是由一个或许多个“widgets”对象构成的。
所有的widgets都从
基类GtkWidget派生。
例如,应用程序的主窗口是GtkWindow类widget,窗口的工具条是
GtkToolbar类widget。
一个GtkWindow是一个GtkWidget,但一个GtkWidget兵不是一个
GtkWindow,子类widgets继承自父类并扩展了父类的功能而成为一个新类,这就是标准
的面向对象编程OOP(Object
Oriented
Programming)思想。
我们可以查阅GTK+参考手册找到widgets直接的继承关系。
对于GtkWindow它的继承链看
起来像这样:
GObject
+----GInitiallyUnowned
+----GtkObject
+----GtkWidget
+----GtkContainer
+----GtkBin
+----GtkWindow
因此,GtkWindow继承自GtkBin,GtkBin继承自GtkContainer,等等。
在第一个程序中,
你不需要担心GtkWidget对象。
各widget之间的继承链之所以重要是因为当你查找某个
widget的函数,属性和信号时,你应该知道它的父类的函数,属性和信号也被此widget继
承了,可以直接使用。
在第二部分讲述此实例的代码时,你能更清楚的认识到这一点。
我们来看命名规则,命名规则带来的好处是非常便于使用。
我们能够清楚的看出对象或
函数是哪个库中的。
以Gtk开头的所有对象都是在GTK+中定义的。
稍后我们会看到类似
GladeXML以Glade开头的是Libglade库对象或函数,GError以G开头的在GLib库定义。
所
有Widgets类都遵循标准camelcase命名习惯。
所有操作函数都以下划线组合小写字母单词
命名。
如gtk_window_set_title()设置GtkWindow对象的标题属性。
你需要的所有参考文档都可以从以下网站获得:
library.gnome.org/devel/references,
分区GTK+GNOME的第1页
不过,使用Devhelp更方便,它甚至可以作为一个包来分发。
Devhelp可以浏览或搜索任
何安装在你系统上的库的相关文档,当然前提是你必须安装了这些文档。
IntroductiontoGlade3
Glade是一种开发GTK+应用程序的RAD(Rapid
Application
Development)工具。
Glade自身就是一个GTK+应
用程序,因为它就是用GTK+开发出来的^_^
Glade用来简化UI控件的设计和布局操作,进行快速开
发。
(译者注:
当然,还不仅如此,Glade的设计初衷是把界面设计与应用程序代码相分离,界面的修改
不会影响到应用程序代码)Glade设计的界面保存为glade格式文件,它实际上是一种XML文件。
Glade起先能根据创建的GUI自动生成C语言代码(你仍然能找到此类相关的实例),后来可以利用
Libglade库在运行时动态创建界面,到了Glade3,这些方法都不赞成使用了。
这是因为,Glade需要做的唯
一的事就是生成一个描述如何创建GUI的glade文件。
这给编程人员提供了更多的灵活性和弹性,避免了用
户界面部分微小的改变就要重新编译整个应用程序,同时其语言无关性,几乎所有的编程语言都可以使用
Glade。
Glade3进行了重新设计,与之前的版本如Glade2有巨大的改变。
2006年Glade3.0发布,你可以自由获取最
新版本进行开发。
软件包管理器如aptitude等应该都有Glade3的安装包,不过请注意:
有个数字3,因
为"glade"是老版本的Glade2,"Glade‐3"或"Glade3"才是新版本。
你也可以从glade.gnome.org下载。
GettingFamiliarwiththeGladeInterface
启动Glade3,让我们来看看其主界面:
左边的是"Palette"就像是一个图形编辑程序,可以用它上面的GtkWidgets来设计你的用户界面。
中间部分
(刚启动时是空白一片)是"Editor"所见即所得的编辑器。
在右边,上部是"Inspector",下部是widget
"Properties"。
Inspector以树形显示当前创建的控件的布局,可以对控件进行选择。
我们通过Properties中各
项内容来设置widgets的属性,包括设置widgets的信号回调函数。
我们先创建一个顶层窗口并保存。
点击Palette上"Toplevels"分组框中的GtkWindow图标,你会看到一个灰
色窗口出现在Glade中间的Editor区域。
这是GtkWindow的工作区:
分区GTK+GNOME的第2页
窗口管理器(如GNOME)会自动加上窗口标题,关闭按钮等,因此我们编辑时看不见。
使用Glade时,我
们总是需要首先创建一个顶层窗口,典型的是创建一个GtkWindow。
以"tutorial.glade"文件名保存工程。
这个文件是一个XML文件,你可以在文本编辑器中打开它:
xmlversion="1.0"encoding="UTF-8"standalone="no"?
>
DOCTYPEglade-interfaceSYSTEM"glade-2.0.dtd">
--Generatedwithglade33.4.0onTueNov2014:
05:
372007-->
GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK|
GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK
你看,这就是一个简单的XML文件,在part2中我们会用C语言调用Libglade库来解析这个XML文件并在运行
时生成UI。
XML文件很容易用Python应用程序或其它任何语言来解析。
Glade能在修改过程中自动保存到该
文件。
退出文本编辑器,回到Glade我们继续。
ManipulatingWidgetProperties
现在,Glade的Editor区显示的是一个空的GtkWindowwidget。
我们来修改它的属性。
在Properties面板,
你会看到4个选项卡:
'General','Packing','Common',和'Signals'。
我们先来谈谈前面的两个。
GtkWidgets有许多属性,这些属性定义了它们的功能和现实方式。
如果你查阅一下GTK+的开发参考文档,找到GtkWidget的"Properties"一项,列出了GtkWindow的特有属
性,这些在Glade属性面板的"General"选项卡中,并且每个widget的属性都会不一样。
widget属性名称是我
们的应用程序直接获取的信息,把此GtkWindow的"name"由"window1"修改为"window"。
添加"GTK+
Text
Editor"到"Window
Title"属性:
分区GTK+GNOME的第3页
我们稍后讲述"Packing",先来看看"Common",这里也包括属性设置,不过我们不能在开发人员参考文档
中相应的widget属性下看到它们,这是因为这些属性是继承自父类的属性。
在参考文档的"Object
Hierarchy"里你将会看到GtkWindow的父类GtkContainer,连接到GtkContainer属性项你将会看到一个"borderwidth",
而在Glade的属性面板中GtkWindow继承了这个属性,你可以在"Common"选项卡底部找到。
我们
以后会讲到GtkContainer,到这里,你应该清楚地知道对象继承链是多么重要了。
因为大部分widgets都从
GtkContainer继承,因此Glade把它的属性放到了"Common"
Tab下。
参考文档的"Object
Hierarchy",GtkContainer由GtkWidget继承。
链接到GtkWidget,你会看到其大部分的属
性都列在了Glade属性面板的"Common"
tab中。
这些属性是所有GTK+
widgets的公共属性,因为它们都继承
自GtkWidget。
SpecifyingCallbackFunctionsforSignals
当某些对程序员有意义的事情发生时,控件对象就发出一个信号"signal"。
这同Visual
Basic中的"events"类似。
当用户与界面进行交互时,界面元素发出相应的信号,程序员
可以决定哪些信号需要捕获并连接到一个回调函数,完成某些任务。
我们遇到的第一个信号,也是你在所有GTK+应用程序中都会碰到的,是由GtkObject发出
的"destroy"信号。
当一个GtkObject对象销毁时就发出"destroy"信号。
这非常重要,因为当
用户通过点击一个widget顶部的"X"来关闭时,widget就销毁了。
我们需要捕获这个信号
并正确地退出我们的应用程序。
在我们正式为此GUI写代码时做这件事是最好的,不过先
得在Glade中指定响应"destroy"信号的具体函数。
切换到属性面板的"Signals"tab,你将看到一个树形列表,显示了当前widget及其父类对象
的所有信号。
这些与参考文档相符。
在"Handler"列下点击灰色文本"here>"并开始编辑它,从下拉列表框中选
择"on_window_destroy"并按回车键。
我们也可以键入任何名字,不过Glade提供的下拉框
列出了通用的回调函数习惯命名。
这个值如何使用得看程序员如何连接信号与回调函数。
在这里,我们把GtkWindow的"destroy"信号连接到"on_window_destroy"函数名上。
在
part2中我们会看到这一点的。
分区GTK+GNOME的第4页
到这里,我们有了一个GUI,可以编写代码显示我们的空窗口并在点击了关闭按钮时退出
程序,你可以用C,Python或任何其它语言。
在此向导中,我将会充分地向你展示如何
在编写任何代码前就用Glade3建立起完整的GUI.不过,为了满足你的好奇心,同时也让
你了解到要实现这个Glade用户接口,代码将会是多么的简单,请看代码:
InC
/*
Firstruntutorial.gladethroughgtk-builder-convertwiththiscommand:
gtk-builder-converttutorial.gladetutorial.xml
Thensavethisfileasmain.candcompileitusingthiscommand
(thosearebackticks,notsinglequotes):
gcc-Wall-g-otutorialmain.c`pkg-config--cflags--libsgtk+-2.0`-export-dynamic
Thenexecuteitusing:
./tutorial
*/
#include
void
on_window_destroy(GtkObject*object,gpointeruser_data)
{
gtk_main_quit();
}
int
main(intargc,char*argv[])
{
GtkBuilder*builder;
GtkWidget*window;
gtk_init(&argc,&argv);
builder=gtk_builder_new();
gtk_builder_add_from_file(builder,"tutorial.xml",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(window);
gtk_main();
return0;
分区GTK+GNOME的第5页
}
InPython(note:
youmustsetthe'visible'propertyof'window'to"Yes"inthe'Common'
propertiestabinGlade)
#!
/usr/bin/envpython
#Firstruntutorial.gladethroughgtk-builder-convertwiththiscommand:
#gtk-builder-converttutorial.gladetutorial.xml
#Thensavethisfileastutorial.pyandmakeitexecutableusingthiscommand:
#chmoda+xtutorial.py
#Andexecuteit:
#./tutorial.py
importpygtk
pygtk.require("2.0")
importgtk
classTutorialApp(object):
def__init__(self):
builder=gtk.Builder()
builder.add_from_file("tutorial.xml")
builder.connect_signals({"on_window_destroy":
gtk.main_quit})
self.window=builder.get_object("window")
self.window.show()
if__name__=="__main__":
app=TutorialApp()
gtk.main()
在这部分,我将不会深入讲解这些实现代码,而把注意力放在Glade3上。
不过你已经看
到了,实现一个Glade创建的用户接口是多么的简单。
AddingWidgetstotheGtkWindow
查阅参考文档你会看到GtkWindow继承自GtkContainer。
继承自GtkContainer的widgets就是一个容器
widgets,也就是说它们可以容纳其它的widgets。
这是GTK+编程的一个基本理念。
如果你是一个Windows程
序员,你会期望着拖一堆的widgets到窗口上,并摆放好它们的位置即可。
不过GTK+并不是这样工作地‐‐‐‐有
更好的理由。
GTK+的widgets可以装填到不同的容器,容器能装填到其它的容器中。
有不同的装填属性设置可以控制
widgets在容器内如何分配空间,这样我们就可以创建出十分复杂的GUI界面,而不用写任何代码来调整
widgets大小尺寸和位置。
因为GTK+为我们做了这一切。
不过这对于一个GTK+程序员新手来说也许是一个难以理解的概念,让我们用事实来说话!
GtkWindow继承自GtkBin容器,GtkBin是只能容纳一个子widget的容器,但是我们的界面需要3个元素:
菜单
条,文本编辑区,状态栏。
因此,我们使用GtkVBox,它可以容纳一个以上的子widgets,并按照垂直排
列。
(GtkHBox按照水平排列子widgets)注:
这里的"子widgets"是指容器中容纳的属于此容器的widgets
在Palette面板上"Container"分组框下的GtkVBox图标上点击。
此时"Select"工具条按钮弹起,并且鼠标在
Glade编辑区上显示为带有"+"的GtkVBox图标。
在灰色的空窗口区点击,就放置了一个GtkVBox,此时弹出
一个对话框询问"Numberofitems",设置GtkVBox的行数,我们选择3行。
分区GTK+GNOME的第6页
编辑区的
GtkWindow现在有三行。
Glade窗口顶部的
"Select"工具栏图标转换到按下状态,即允许你在编辑区
选择任意的
widgets。
接下来添加一个
GtkMenuBar到GtkVBox的最顶上一行,
GtkMeneBar在Glade的"Container"分组框下
分区
GTK+GNOME的第
7页
现在,找到
"Container"下的GtkScrolledWindow并添加到中间一行。
完成这一步后除了中间一行被选中状态
外看不出有什么变化。
这是因为
GtkScrolledWindow没有任何初始化可视元素。
它仅仅是一个容器,当它容
纳的子
widgets变得太大时它提供滚动条。
我们的编辑器需要滚动条支持。
点击"Control
and
Display"分组框下的
GtkTextView并添加到
GtkScrolledWindow上(中间一行)。
分区
GTK+GNOME的第
8页
最后,点击
"Control
and
Display"分组框下的
GtkStatusbar并添加到最底部一行。
这就建好了我们文本编辑器的
UI布局。
在Inspector中你会看到
widgets的包容关系。
分区
GTK+GNOME的第
9页
在Inspector中选择widgets是很方便的,因为当widgets相互重叠时你在编辑区不能选择了。
比如你不能在编
辑区中点击GtkScrolledWindow因为我们只能看到它包容的子widgets,你只能在Inspector中选择。
之前我提到装填的概念对一个GTK+程序员新手来说不好理解。
因此,我将向你展示不同的装填方式是如何
影响你的布局设计的。
HowPackingEffectstheLayout
从上面的界面设计过程,你也许会惊叹Glade如此的智能。
它是如何知道我们不想状态栏太高?
如果你调整
窗口大小,它又是如何知道应该让文本编辑框自动缩放来填充窗口变化的空间?
哈哈,Glade靠猜的!
它
应用了默认设置,我们通常需要如此,不过不总是这样。
了解装填的最好方式是试验各种不同的装填属性,观察Glade如何响应。
你应该了解的关于装填和空间分配:
homogeneous:
此属性设置,则告诉GTK+为每个子widgets分配同样大小的空间。
expand:
子widgets的装填属性,确定在容器增长时,此子widgets是否获得额外的空间。
fill:
子widgets装填属性,确定子widgets是否利用分配到的额外空间。
来看默认装填属性,GtkScrolledWindow的"expand"=TRUE表示当其所在容器增长时它要获得空间分
配,"fill"=TRUE表示它将扩充自己来利用额外空间。
这是我们想要的效果。
WidgetPropertyValue
GtkVBox"vbox1"homogeneousFALSE
GtkMenuBar"menubar1"expandFALSE
fillTRUE
GtkScrolledWindow"scrolledwindow1"expandTRUE
fillTRUE
GtkStatusbar"statusbar1"expandFALSE
fillTRUE
现在我们来看homogeneous都干嘛了。
在Inspector中选择GtkVBox并设置其"Homogeneous"="Yes",这