您的位置:首页 > 产品设计 > UI/UE

GTK+ and Glade3 GUI Programming Tutorial--中文系列

2009-03-28 20:04 459 查看
原文链接:

Micah Carrick

www.micahcarrick.com/12-24-2007/gtk
-glade-tutorial
-part
-1.html

Part 1

Quick Overview of GTK+ 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+
中定义的。

稍后我们会看到类似
Glade
XML

Glade
开头的是
Libglade
库对象或函数,
GError

G
开头的在
GLib
库定义。所有
Widgets
类都遵循标准
camelcase
命名习惯。所有操作函数都以下划线组合小写字母单词命名。如
gtk_window_set_title
()设置
GtkWindow
对象的标题属性。

你需要的所有参考文档都可以从以下网站获得:
library.gnome.org/devel/references

,

不过,

使用
Devhelp
更方便,

它甚至可以作为一个包来分发。
Devhelp
可以浏览或搜索任何安装在你系统上的库的相关文档,

当然前提是你必须安装了这些文档。

Introduction to Glade3

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
下载。

Getting Familiar with the Glade Interface
启动
Glade3


让我们来看看其主界面:



左边的是
"Palette"
就像是一个图形编辑程序,

可以用它上面的
GtkWidgets
来设计你的用户界面。中间部分(刚启动时是空白一片)是
"Editor"
所见即所得的编辑器。在右边,

上部是
"Inspector"


下部是
widget "Properties"

Inspector
以树形显示当前创建的控件的布局,

可以对控件进行选择。我们通过
Properties
中各项内容来设置
widgets
的属性,

包括设置
widgets
的信号回调函数。

我们先创建一个顶层窗口并保存。点击
Palette

"Toplevels"
分组框中的
GtkWindow
图标,

你会看到一个灰色窗口出现在
Glade
中间的
Editor
区域。这是
GtkWindow
的工作区:



窗口管理器(如
GNOME
)会自动加上窗口标题,

关闭按钮等,

因此我们编辑时看不见。使用
Glade
时,

我们总是需要首先创建一个顶层窗口,典型的是创建一个
GtkWindow



"tutorial.glade"
文件名保存工程。这个文件是一个
XML
文件,

你可以在文本编辑器中打开它:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3
3.4.0 on Tue Nov 20 14:05:37 2007 -->
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<placeholder/>
</child>
</widget>
</glade-interface>

你看,这就是一个简单的
XML
文件,


part2
中我们会用
C
语言调用
Libglade
库来解析这个
XML
文件并在运行时生成
UI

XML
文件很容易用
Python
应用程序或其它任何语言来解析。
Glade
能在修改过程中自动保存到该文件。退出文本编辑器,回到
Glade
我们继续。

Manipulating Widget Properties
现在,
Glade

Editor
区显示的是一个空的
Gtk
Window widget
。我们来修改它的属性。在
Properties
面板,

你会看到
4
个选项卡:'General', 'Packing', 'Common', 和 'Signals'。我们先来谈谈前面的两个。

GtkWidgets
有许多属性,这些属性定义了它们的功能和现实方式。

如果你查阅一下
GTK+
的开发参考文档,

找到
GtkWidget

"Properties"
一项,

列出了
GtkWindow
的特有属性,

这些在
Glade
属性面板的
"General"
选项卡中,

并且每个
widget
的属性都会不一样。
widget
属性名称是我们的应用程序直接获取的信息,

把此
GtkWindow

"name"

"window1"
修改为
"window"
。添加
"GTK+ Text Editor"

"Window Title"
属性:



我们稍后讲述
"Packing"


先来看看
"Common"


这里也包括属性设置,

不过我们不能在开发人员参考文档中相应的
widget
属性下看到它们,这是因为这些属性是继承自父类的属性。在参考文档的
"Object Hierarchy"
里你将会看到
GtkWindow
的父类
GtkContainer


连接到
GtkContainer
属性项你将会看到一个
"border-width"


而在
Glade
的属性面板中
GtkWindow
继承了这个属性,

你可以在
"Common"
选项卡底部找到。我们以后会讲到
GtkContainer


到这里,

你应该清楚地知道对象继承链是多么重要了。因为大部分
widgets
都从
GtkContainer
继承,

因此
Glade
把它的属性放到了
"Common" Tab
下。

参考文档的
"Object Hierarchy"

GtkContainer

GtkWidget
继承。链接到
GtkWidget


你会看到其大部分的属性都列在了
Glade
属性面板的
"Common" tab
中。这些属性是所有
GTK+ widgets
的公共属性,

因为它们都继承自
GtkWidget


Specifying Callback Functions for Signals

当某些对程序员有意义的事情发生时,

控件对象就发出一个信号
"signal"
。这同
Visual Basic
中的
"events"
类似。当用户与界面进行交互时,

界面元素发出相应的信号,

程序员可以决定哪些信号需要捕获并连接到一个回调函数,完成某些任务。

我们遇到的第一个信号,也是你在所有
GTK+
应用程序中都会碰到的,是由
GtkObject
发出的
"destroy"
信号。当一个
GtkObject
对象销毁时就发出
"destroy"
信号。这非常重要,因为当用户通过点击一个
widget
顶部的
"X"
来关闭时,
widget
就销毁了。我们需要捕获这个信号并正确地退出我们的应用程序。在我们正式为此
GUI
写代码时做这件事是最好的,

不过先得在
Glade
中指定响应
"destroy"
信号的具体函数。

切换到属性面板的
"Signals"tab
,你将看到一个树形列表,显示了当前
widget
及其父类对象的所有信号。

这些与参考文档相符。


"Handler"
列下点击灰色文本
"<Type here>"
并开始编辑它,

从下拉列表框中选择
"on_window_destroy"
并按回车键。我们也可以键入任何名字,

不过
Glade
提供的下拉框列出了通用的回调函数习惯命名。这个值如何使用得看程序员如何连接信号与回调函数。在这里,

我们把
GtkWindow

"destroy"
信号连接到
"on_window_destroy"
函数名上。在
part2
中我们会看到这一点的。



到这里,

我们有了一个
GUI


可以编写代码显示我们的空窗口并在点击了关闭按钮时退出程序,

你可以用
C


Python
或任何其它语言。在此向导中,

我将会充分地向你展示如何在编写任何代码前就用
Glade3
建立

起完整的
GUI.
不过,

为了满足你的好奇心,

同时也让你了解到要实现这个
Glade
用户接口,代码将会是多么的简单,请看代码:

In C
/*

First run tutorial.glade through gtk-builder-convert with this command:

gtk-builder-convert tutorial.glade tutorial.xml

Then save this file as main.c and compile it using this command

(those are backticks, not single quotes):

gcc -Wall -g -o tutorial main.c `pkg-config --cflags --libs gtk+-2.0` -export-dynamic

Then execute it using:

./tutorial

*/

#include <gtk/gtk.h>

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;

}

In Python (note: you must set the 'visible' property of
'window' to "Yes" in the 'Common' properties tab in Glade)

#!/usr/bin/env python

# First run tutorial.glade through gtk-builder-convert with this command:

# gtk-builder-convert tutorial.glade tutorial.xml

# Then save this file as tutorial.py and make it executable using this command:

# chmod a+x tutorial.py

# And execute it:

# ./tutorial.py

import pygtk

pygtk.require("2.0")

import gtk

class TutorialApp(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
创建的用户接口是多么的简单。

Adding Widgets to the GtkWindow

查阅参考文档你会看到
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
图标。在灰色的空窗口区点击,就放置了一个
Gtk
VBox
,此时弹出一个对话框询问
"Number of items"


设置
GtkVBox
的行数,我们选择
3
行。





编辑区的
GtkWindow
现在有三行。
Glade
窗口顶部的
"Select"
工具栏图标转换到按下状态,即允许你在编辑区选择任意的
widgets


接下来添加一个
GtkMenuBar

GtkVBox
的最顶上一行,
GtkMeneBar

Glade

"Container"
分组框下



现在,找到
"Container"
下的
GtkScrolledWindow
并添加到中间一行。完成这一步后除了中间一行被选中状态外看不出有什么变化。这是因为
GtkScrolledWindow
没有任何初始化可视元素。它仅仅是一个容器,当它容纳的子
widgets
变得太大时它提供滚动条。我们的编辑器需要滚动条支持。



点击
"Control and Display"
分组框下的
GtkTextView
并添加到
GtkScrolledWindow
上(中间一行)。



最后,点击
"Control and Display"
分组框下的
GtkStatusbar
并添加到最底部一行。



这就建好了我们文本编辑器的
UI
布局。在
Inspector
中你会看到
widgets
的包容关系。




Inspector
中选择
widgets
是很方便的,因为当
widgets
相互重叠时你在编辑区不能选择了。比如你不能在编辑区中点击
GtkScrolledWindow
因为我们只能看到它包容的子
widgets


你只能在
Inspector
中选择。

之前我提到装填的概念对一个
GTK+
程序员新手来说不好理解。因此,我将向你展示不同的装填方式是如何影响你的布局设计的。

How Packing Effects the Layout

从上面的界面设计过程,你也许会惊叹
Glade
如此的智能。它是如何知道我们不想状态栏太高?如果你调整窗口大小,

它又是如何知道应该让文本编辑框自动缩放来填充窗口变化的空间?哈哈,
Glade
靠猜的!它应用了默认设置,我们通常需要如此,不过不总是这样。

了解装填的最好方式是试验各种不同的装填属性,观察
Glade
如何响应。

你应该了解的关于装填和空间分配:
homogeneous
:此属性设置,则告诉
GTK+
为每个子
widgets
分配同样大小的空间。

expand
:子
widgets
的装填属性,确定在容器增长时,此子
widgets
是否获得额外的空间。

fill
:子
widgets
装填属性,确定子
widgets
是否利用分配到的额外空间。

来看默认装填属性,
GtkScrolledWindow

"expand"=TRUE
表示当其所在容器增长时它要获得空间分配,
"fill"=TRUE
表示它将扩充自己来利用额外空间。这是我们想要的效果。

Widget
Property
Value
GtkVBox "vbox1"
homogeneous
FALSE
GtkMenuBar "menubar1"
expand
FALSE
fill
TRUE
GtkScrolledWindow "scrolledwindow1"
expand
TRUE
fill
TRUE
GtkStatusbar "statusbar1"
expand
FALSE
fill
TRUE
现在我们来看
homogeneous
都干嘛了。在
Inspector
中选择
Gtk
VBox
并设置其
"Homogeneous"="Yes"
,这表示
"vbox1"
将分配同样大小的空间给其包含的子
widgets
。既然其
3
个子
widgets

"fill"=TRUE
,那么它们将填满分配到的空间。



现在设置
GtkScrolledWindow

"Expand"=Yes

"Fill"=NO
。此时额外空间分配给
GtkScrolledWindow
,但是它并不扩充自己来利用分配到的额外空间。

我知道你认为这看起来很奇特,不过随着你深入了解
Glade


你将会清楚地知道装填属性是怎么工作的,并且你会惊叹为了改变
GUI
各元素位置和尺寸竟然只需要做如此少的工作就能完成。

Editing the Menu (or Toolbar)

Glade3
拥有一个新的菜单条和工具条编辑器,尽管我们的向导里不使用
GtkToolBar
,不过它的处理与
GtkMenuBar
很相似。我们将利用
Glade3
的菜单编辑器来删除不需要的菜单项并对需要使用的菜单项设置信号处理。

你可以使用
Glade

Inspector
来删除,可以在
Glade
的属性面板中设置信号处理,不过
Glade3
的菜单编辑器更容易做这些工作。

在编辑区或通过
Inspector
选择
GtkMenuBar
,单击右键选择
"Edit"
启动菜单编辑器。



菜单编辑器包括的属性设置很像
Glade
主界面属性面板,而底部的信号设置与
Glade
属性面板中的
"Signals"tab
很像。只不过菜单编辑器中左边是树形列表显示。可以很轻易地添加或删除菜单项。移除
"_View"
菜单项。我们的向导中不使用这个菜单。对剩余的菜单项,我们需要重新命名,以便于在源代码中能清楚明了地引用它们。每个菜单项修改都一样,所以我只讲
"New"
,记住,所有这些菜单编辑器能做的工作在
Inspector
和属性面板中也能完成。

Final Touches to the Main Window

对于
"textview1"

"textview2"
这种命名的引用十分不利于在源代码中使用,因此需要重新修改以下
widgets
的名称(记住,名称在属性面板的
"General"tab


1 "textview1"
改为
"text_view"

2 "statusbar1"
改为
"statusbar"

为了使其看上去更漂亮一些,我们为
GtkScrolledWindow
增加阴影和边框

1
在属性面板的
"General"tab
中把
scrolledwindow1

"Shadow Type"
改为
"Etched in"

2
属性面板的
"Common"tab
中把
scrolledwindow1

"Border Width"
改为
1

3

"General"
属性中把
"text_view"

"Left Margin"
设为
2

4

"General"
属性中把
"text_view"

"Right Margin"
设为
2

Getting Additional Help Using Glade

对使用
Glade
过程中的更多问题,可以询问

glade-users mailing list



GTK+ Forums
.

What Next?


GTK+ and
Glade3
GUI Programming Tutorial - Part 2

中将选择一个确定的编程语言来实现我们刚刚创建的
GUI
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐