http://blog.csdn.net/xbwee/article/details/4034314
原文链接:
Micah Carrick
www.micahcarrick.com/01-01-2008/gtk
-glade-tutorial
-part-3.html
Part 3
Writing a Basic Program to Implement the Glade File
在这一部分,
我将示范一个非常简单的程序,
用来解析我们在
part1
中用
Glade3
创建的
GUI
文件
tutorial.glade
,
并显示我们
GTK+
文本编辑器的主窗口。我会先讨论
GTK+
的一些概念然后分别以
C
语言和
Python
语言来给出实现代码。如果你选择其中之一,
那么你可以跳过另外一门语言的介绍部分。
Setting Up Your Development Environment
为完成这部分向导的
GTK+
编程,你需要一个文本编辑器,
一个终端,,
GTK+
开发库,
以及
Devhelp
。
Devhelp
是开发人员的参考帮助。如果你是
Linux
新手,那么有更多的选择等着你。并没有一个所谓标准的编辑器或者是
IDE
,
许多开发人员都仅仅使用自己喜欢的文本编辑器和终端。尽管也有一些功能齐全的
IDE
可以选择,
不过你应该首先使用比较简单的文本编辑器加上终端即可,
以免被
IDE
的特性和自动化功能弄迷糊,
浪费不必要的时间。
我使用
gedit
,
GNOME
的默认文本编辑器。
gedit
有一些有用的插件可以使用。我写了一个
Gedit Symbol Browser Plugin
可以让你快速地跳转到源代码的函数定义。
你需要的开发库取决于你使用
C
还是使用
Python
,
对于不同的开发平台及发布平台会有很大不同,
不过我会对此提供一些有用的信息。如果在安装开发包和发布产品时还出现问题的话,
可以到
寻找答案。
在
Linux
上,
你通常可以使用分发包管理器获得你所需要的所有开发包并解决其依赖性。例如,
在
Ubuntu
上你只需要使用命令:
sudo aptitude install libgtk-2.0-dev
,
即可安装好
GTK+
开发包,以及其相关依赖项。
注意,需要安装的是
"development package"
,
Ubuntu/Debian
中以
-dev
结尾的包,
在
Redhat/Fedora
中以
-devel
结尾。这种包包括了使用相应的库来开发应用程序所需要的头文件和其它包含文件。请记住,
"package"
允许你能过运行应用程序,而
"package-dev"
或
"package-devel"
允许你使用库开发应用程序。
另外你还会见到
-doc
后缀的包,
比如
"libgtk2.0-doc"
,这是相应库的开发文档,
安装之后你就可以使用
Devhelp--the GNOME developer‘s help browser
.
来浏览相关文档。
如果你使用
C
,你应该安装以下开发包及其依赖项
:build-essential, libgtk2.0-dev, libgtk2.0-doc, libglib2.0-doc, devhelp.
如果你用
Python
,
你应该安装以下开发包及其依赖项:
python2.5-dev, python2.5-doc, python2.5-gtk2, python-gtk2-doc, python-gobject-doc, devhelp.
GtkBuilder and LibGlade
如果你能回忆起来的话,
我们在
part1
利用
Glade
创建的
tutorial.glade
文件是一个描述
GUI
界面的
XML
文件。实际的
GUI
是由我们的应用程序来创建的。因此,
应用程序需要解析
XML
文件并创建
widgets
的对象实例。不过这个任务可以使用两个库来完成:
Libglade
库,
用来解析
glade
文件并创建
widgets
对象实例。使用
Libglade
库是最常用的方式,
在其它一些开发向导或教程中都能看到。然而,
自此
GTK+2.12
,
就包含了一个叫
GtkBuilder
的对象,
它是
GTK+
自身的一部分并用来取代
Libglade
库。也因此,在我们的开发向导中我们将使用
GtkBuilder
。不过,
你得知道的是,
你在网络上看到的教程中凡是使用
Libglade
库的,
都可以使用
GtkBuilder
来代替。
在写本系列的时候,
GtkBuilder
还是一个新东西,
因此
Glade
尚未支持
GtkBuilder
格式文档,(译者注:自
Glade3.6.0
版本,
提供了对两种格式的支持即
Libglade
和
GtkBuilder
格式)
GtkBuilder
格式就是
XML
格式文件,
但是有一点不同。这意味着
GtkBuilder
使用
glade
文件时,
需要进行格式转换。
GTK2.12
提供了转换脚本命令来做这件事,
这个脚本连同开发库一起安装。现在你已经装上了
^_^
你可以参考关于
Libglade/GtkBuilder
常见问题的答案:
Libglade to GtkBuilder F.A.Q.
.
使用如下命令来把
Libglade
格式文件
tutorial.glade
转换为
GtkBuilder
格式文件
tutorial.xml
文件:
gtk-builder-convert tutorial.glade tutorial.xml
而
tutorial.xml
文件是我们的应用程序将要用来进行解析的,
不过我们仍然需要
glade
文件以便可以使用
Glade
进行修改。这是必需的,直到
Glade3.6
版本支持
GtkBuilder
格式文件为止。(译者注:
Mar 16 2009
,
Glade3.6.0 released
。此版本及以后版本可以直接使用
xml
文件并且自动保存所做的修改)
The Minimal Application
现在我们开始写代码!首先回顾一下到目前为止我们都做了哪些工作
1
使用
Glade
,创建了描述用户界面的
tutorial.glade
文件
2
我们选择了开发语言
C
和
Python
3
准备了一个文本编辑器和一个终端
4
安装了进行
GTK+
开发所需要的所有库
5
使用
gtk-builder-convert
命令把
tutorial.glade
文件转换成了
GtkBuilder
使用的
tutorial.xml
文件。
现在,
在深入讲解每一行代码的细节之前,
先来写一个最简单的程序来验证一切都能正常工作,
并熟悉开发流程。因此,
打开你的文本编辑器,
输入以下内容:
C
语言
#include
void
on_window_destroy (GtkObject *object, gpointer user_data)
{
gtk_main_quit();
}
int
main (int argc, 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 ();
return 0;
}
命名为
main.c
并保存到
tutorial.xml
所在目录。
Python
语言
import sys
import gtk
class TutorialTextEditor:
def on_window_destroy(self, widget, data=None):
gtk.main_quit()
def __init__(self):
builder = gtk.Builder()
builder.add_from_file("tutorial.xml")
self.window = builder.get_object("window")
builder.connect_signals(self)
if __name__ == "__main__":
editor = TutorialTextEditor()
editor.window.show()
gtk.main()
命名为
tutorial.py
并保存到
tutorial.xml
所在目录。
Compiling and Running the Application
C
语言
C
是一种编译语言,
需要使用
gcc
编译器把源代码转换为二进制可执行代码。为了让
gcc
知道
GTK+
链接库位置以及编译标识,我们使用
pkg-config
。当我们安装
GTK+
开发包时,
一个叫
"gtk
+-2.0.pc
"
的配置文件也安装了,
它告诉
pkg-config
我们系统上安装的
GTK+
库版本以及包含文件位置等信息。
输入以下命令;
pkg-config --modversion gtk+-2.0
终端输出将是你安装的
GTK+
版本号。我的系统上显示为
2.12.0
。现在来看编译
GTK+
应用程序时需要的编译器标识:
pkg-config --cflags gtk+-2.0
输出将是一堆的
-I
开关选项指出编译器使用的包含文件。这能让
gcc
知道到哪去找我们应用程序中
"#include"
所列出的包含文件。
每当使用了
"#include"
并引用了非标准
C
库头文件时,
都需要使用
"I/path/to/library"
选项传给
gcc
。这些库可以装在不同的地方,这根据分发要求,操作系统或使用者意愿来定。而
pkg-config
为我们掌控这一切。
编译我们的程序。终端输入以下命令(确保你当前目录为
main.c
和
tutorial.xml
所在目录)
:
gcc
-Wall
-g
-o
tutorial
main.c
-export-dynamic
`pkg-config
--cflags
--libs
gtk+-2.0`
其中
"-Wall"
选项告诉
gcc
显示警告信息。
"-g"
选项产生调试信息,
当你使用调试器如
gdb
进行单步调试时这非常有用。
" -o
tutorial"
告诉
gcc
输出的可执行文件名。
"main.c"
是
gcc
将对其进行编译的源文件。
"-export-dynamic"
关系到我们如何连接信号与回调函数,这在以后讲解。最后出现的是
pkg-config
命令。
注意,
pkg-config
命令是用反引号
``
而不是单引号
‘‘
。反引号在数字键
1
的旁边。这告诉
shell
先执行
pkg-config
--cflags
--libs
gtk+-2.0
然后将其结果输出复制到
gcc
命令的末尾。
pkg-config
命令可以在任何系统上使用,而不用考虑库的安装位置。
编译之后,
我们可以运行它:
./tutorial
你会看到一些警告信息
"Gtk-WARNING**
:
Could not find signal handler ‘xxxxxx‘"
,
别担心,这些信息告诉我们在
glade
文件中定义的一些信号在程序中没有相关的处理程序。讲到代码时我在讲解这些。不过你应该看到显示了一个窗口,通过点击
"X"
来关闭它。
如果由于某种原因你不能编译并执行你的程序,可以把错误信息贴到
以寻求帮助。
Python
语言
因为
Python
是解释性语言,所以我们不需要编译程序。只是调用
Python
解释器,
源代码中第一行就是做这件事情。为了运行我们的程序,
使用以下命令改变文件访问权限:
chmod a+x tutorial.py
然后可运行:
./tutorial.py
Stepping Through the Code
注意:你应该在我讲到某个函数时顺便查阅
GTK+
开发文档。它会是你最好的朋友。安装
Devhelp
并使用它。考虑到也许你不能安装
Devhelp
的情况,在我讲到一个新函数时将会提供在线文档的链接。
Including the GTK+
Library
C
语言
希望你足够了解了
C
编程并能知道第一行
"#include "
是怎么回事。否则,你应该先看看
C
基础编程向导。包含了
gtk.h
,我们就同时间接地包含了多需的其它头文件。事实上,
我们包含了所有
GTK+
库及其依赖的
GLib
库部分头文件。想知道具体有哪些,打开此文件看一看!
Python
语言
希望你足够了解了
Python
编程并能知道前两行
"#import sys"
和
"#import gtk"
是怎么回事。否则,你应该先看看
Python
基础编程向导。现在我们可以访问所有的
gtk.x
类了。
Initializing the GTK+
Library
Python
自动显示初始化了
GTK+
库,
而
C
你必须在调用任何
GTK+
函数前初始化
GTK+
库
gtk_init(&argc
,
&argv);
Building the Interface with GtkBuilder
在不使用任何辅助
GUI
工具开发
GTK+
应用程序时,
程序员需要编写程序来创建每个
widgets
并调用相关函数设置其属性,然后装填到容器中。每个步骤都需要许多行代码才能完成,
非常的繁琐。考虑我们在
part1
中建立的用户
GUI
界面,
超过
20
个
widgets
(包括菜单项)编写代码来创建这些界面需要将近百行代码才能创建并设置好每一个属性。
幸好我们有
Glade
和
GtkBuilder
。仅仅只需要
2
行代码,
GtkBuilder
就能解析
tutorial.xml
文件,创建所有定义的
widgets
并应用其属性,以及建立
widgets
之间包容父子关系。然后,我们就能利用
GtkBuilder
引用
widgets
并控制其行为特性。
C
语言
builder = gtk_builder_new();
gtk_builder_add_from_file(builder, "tutorial.xml", NULL);
第一个变量是在
main
()中定义的
GtkBuilder
类对象指针。我们使用
gtk_builder_new()
来创建实例。所有的
GTK+
对象都以这种方式创建。
这时
builder
还没有任何
UI
元素,我们使用
gtk_builder_add_from_file()
来解析
XML
文件,并把其内容添加到
builder
对象。此函数的第三个参数我们传递了
NULL
,因为现在不需要使用
GError
。我们没有进行任何异常和错误处理,因此一旦有任何异常或错误出现,
我们的程序只能崩溃。异常与错误处理我们后面再讲。
在调用了
gtk_builder_new()
创建了对象实例之后,所有的其它
gtk_builder_xxx
函数都是以创建好的
builder
对象作为第一个参数。这就是
GTK+
用
C
实现的面向对象技术。其它所有
GTK+
对象都是如此方式。
Python
语言
builder=gtk.Builder()
builder.add_from_file("tutorial.xml")
Getting References to Widgets From GtkBuilder
创建好了所有的
widgets
之后我们就可以引用它们了。我们只需要引用一部分,因为其它的已经能很好地完成它们的工作不再需要更多的处理了。例如,
GtkVBox
,容纳了菜单,文本编辑框,状态栏,已经完成了布局工作不需要代码处理了。我们可以在应用程序生命期引用任意一个
widgets
并保存在变量中以备用。在此开发向导中我们仅仅需要引用命名为
"window"
的
GtkWindow
对象,以便显示它。
C
语言
Window=GTK_WIDGET(gtk_builder_get_object(builder, "window"));
首先,
gtk_builder_get_object()
第一个参数是获取的对象所在的
builder
对象,第二个参数是获取对象的名称,
这个名称必须与我们在
Glade
中
"name"
属性一致。函数返回一个
GObject
对象指针,
保存在
window
变量中。参考文档中对象层次结构指出
GtkWidget
从
GObject
继承,
因此一个
GtkWindow
就是一个
GObject
,也是一个
GtkWidget
。这是
OOP
的基本概念,对于
GTK+
编程很重要。
因此
GTK_WIDGET()
宏进行类型转换。你可以用转换宏把
GTK+
的
widgets
转换为它的任意一个子类型,
所有
GTK+
类都有相应的类型转换宏。
GTK_WIDGET(something)
就如同
(GtkWidget*)something
所起的作用一样。
最后,
main
()函数中我们声明一个
GtkWidget
类型的
window
变量而不是
GtkWidget
类型,这纯属是习惯而已。我们也可以把它声明为
GtkWindow*
也对。所有
GTK+
的
widgets
都继承自
GtkWidget
因此我们可以声明指向任何
widgets
的指针为
GtkWidget
类型。许多函数都传递
GtkWidget*
类型的参数,并且许多函数返回的也是
GtkWidget*
类型指针。所以声明为
GtkWidget
类型然后必要时使用转换宏转换为其它
widgets
类型。
Python
语言
self.window = builder.get_object("window")
Connecting Callback Functions to Signals
在
part1
我们指定了许多信号的处理函数,
当有事件发生时
GTK+
就发送相应的信号,
这是
GUI
编程的基础概念。我们的应用程序需要知道用户何时做了何事,然后对此进行响应。你将会看到,我们的程序就是循环等待事件的发生。我们使用
GtkBuilder
来连接在
Glade
中定义的信号和相应的回调函数。
GtkBuilder
会自动查询程序符号表然后正确地连接信号与处理函数。
在
part1
中,
我们定义了
"on_window_destroy"
函数来响应
"window"
的
"destroy"
信号。当一个
GObject
对象销毁时,它会发送
"destroy"
信号,我们的应用程序就无限循环等待事件发生,
当用户关闭主窗口(点击主窗口标题栏的
"X"
按钮)应用程序需要能够终止循环并退出。连接一个回调函数到
GtkWindow
的
"destroy"
信号,就能知道何时终止程序。因此,
"destroy"
信号是几乎所有的
GTK+
应用程序中都会处理的。
注意:本实例中用来连接信号与处理程序的函数与
Libglade
中的
glade_xml_signal_autoconnect()
函数等价。
C
语言
gtk_builder_connect_signals(builder, NULL);
此函数总是需要传递
builder
对象作为第一个参数,第二个参数是用户数据。这很有用,不过现在设为
NULL
即可。这个函数会使用
GModule
,
GLib
的一部分,
动态加载模块来查询应用程序符号表(函数名,
变量名等等),寻找应用程序中能够与
Glade
中指定的回调函数名相符的函数,然后连接到信号。
在
Glade
中我们为
GtkWindow
的
"destroy"
信号指定了回调函数名为
"on_window_destroy"
,因此
gtk_builder_connect_signals()
会在程序中寻找名为
"on_window_destroy"
的处理函数,如果找到则连接到
"signal"
信号。函数原型必须一致才能连接,包括函数名,参数个数类型,返回类型等。
"destroy"
信号属于
Gtk
Object
类,因此可以在开发文档中查找
GtkObject
目录下的
"destroy"signal
找到相应的回调函数原型,根据此原型我们可以定义如下处理函数
:
void
on_window_destroy (GtkObject *object, gpointer user_data)
{
gtk_main_quit();
}
现在,
gtk_builder_connect_signals()
将会找到它并确认与
Glade
中指定的函数匹配,因此就把此函数与
"destroy"
信号连接。当
GtkWindow
对象
"window"
销毁时将会调用上述函数。此函数仅仅是调用了
gtk_main_quit()
来结束循环并退出应用程序。
因为我们不再使用
GtkBuilder
对象了,所以可以将其销毁并释放为
XML
文件分配的空间:
g_object_unref(G_OBJECT(builder))
。
你注意到我们使用
G_OBJECT
宏将
GtkBuilder*
转换为
GOblet*
,
这是必须的因为函数
g_object_unref()
接受
GOblet*
类型参数。而
GtkBuilder
是从
GOblet
继承的。
Python
语言
builder.connect_signals(self)
Showing the Application Windo
w
在进入
GTK+
主循环之前,显示我们的
GtkWindow
类
widget
,否则它是不可见的。
C
语言
gtk_widget_show(window);
此函数设置了
widgets
的
GTK_VISIBLE
标识,告诉
GTK+
可以显示此
widget
了。
Python
语言
editor.window.show()
Entering the GTK+
Main Loop
GTK+
的主循环是一个无限循环,一旦创建了
GUI
并设置好了应用程序,就可以进入主循环等待事件的发生。在主循环中发生了很多魔幻的事情,作为一个新手,可以简单的把它看成是一个循环,做了诸如检查状态,更新
UI
,为事件发送信号等事情。
一旦进入主循环,我们的应用程序就不做任何事了(
GTK+
在做),当用户缩放窗口,最小化,点击,按键等等时,
GTK+
检查每一个事件并发送相应的信号。不过,我们的应用程序仅仅对
"window"
的
"destroy"
信号进行响应。其它一概不管。
C
语言
gtk_main();
Python
语言
gtk.main()
总结
:
1
应用程序使用
GtkBuilder
从
XML
文件创建
GUI
2
应用程序得到主窗口小部件的引用
3
应用程序把
"on_window_destroy"
处理函数连接到
"destroy"
信号
4
应用程序显示窗口
5
应用程序进入
GTK+
主循环
6
用户点击
"X"
按钮关闭窗口,导致
GTK+
主循环发送
"destroy"
信号
7
信号处理函数
"on_window_destroy"
退出
GTK+
主循环
8
应用程序正常终结
What‘s Next?
在接下来的部分,
我将会完成我们的
GTK+
文本编辑器余留的功能,并处理所需的信号。对代码不再详细阐述。
阅读(837) | 评论(0) | 转发(4) |
0
上一篇:GTK+ and Glade3--中文系列-Part2
下一篇:GTK+ and Glade3 GUI Programming
相关热门文章
- test123
- 编写安全代码——小心有符号数...
- 使用openssl api进行加密解密...
- 一段自己打印自己的c程序...
- sql relay的c++接口
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
热门推荐
-->
给主人留下些什么吧!~~
评论热议
GTK+ and Glade3--中文系列-Part3