当前位置:Linux教程 - Gnome - 使用 perl 编写 GNOME 应用程序入门

使用 perl 编写 GNOME 应用程序入门

大家知道, LINUX 下有两大桌面环境,一个是 KDE (K Desktop Enviroment),基于 Qt 图形库,另一个是 GNOME (GNU Network Object Model Environment),基于 Gtk+ 图形库.由于 Qt 库不遵从 GPL 协议,并且获取许可证很不方便,而 GNOME 则很不错,所以应该避免使用 Qt 库和 KDE.

从用户的角度看, GNOME 是一个集成桌面环境和应用程序的套件;从程序员的角度来看,它是一个应用程序开发框架(由数目众多的实用函数库组成).即使用户不运行 GNOME 桌面环境,用 Gnome 编写的应用程序一样可以正常运行.但是这些应用程序是可以很好的和 Gnome 桌面环境集成的.Gnome 的开发结构使开发一致的,易用的和可互操作的应用程序成为可能.

下面我来讲一下如何用 perl 来写一个基于 Gnome 的程序,虽然很简单,但却是完整的,包含有标准的通用界面.

GNOME拥有许多的库和组件,但现在我们只需知道其中的两件:GTK+ 和 GNOME. 你可能听说过 TK ,这是另一种可以使用 perl 来写图形界面应用程序的工具包.TK 的任务是告诉 X Server 如何来画按钮,菜单,对话框等等,并返回一些信号来触发相应的 perl 函数来处理一些变化.作为 perl 程序和 X Server 之间的媒介.而 GTK+ 做着类似的工作,但事实证明,它工作得更加漂亮,它可以提供所有的图形元素,诸如:按钮,文本标签,文本输入等等,使用循环等待事件的方式实现交互.GNOME 库建立了一个抽象于 GTK+ 之上的一层,提供了更高级的图形对象,比如:主应用程序窗口, about 窗口,按钮面板,对话框,颜色与字体选择框,并且提供了与其他 GNOME 环境程序(如spelling checkers, calculators)协作的接口.

此外,Glade 是一种在 Linux 下的类似 Visual Basic 的快速开发环境(IDE),可以使用它方便的写出 perl 代码的 GNOME 应用程序,但为了能明白代码的含义,请继续往下看.

现在先来看一下""hello world""程序,这里有两个版本,第一个使用 GTK+ ,第二个使用 GNOME :

------------------------------------

1 #!/usr/bin/perl -w

2

3 use strict;

4 use Gnome;

5

6 my $NAME = ''Hello World'';

7

8 init Gnome $NAME;

9

10 my $w = new Gtk::Window -toplevel;

11

12 my $label = new Gtk::Label ""Hello, world"";

13 $w->add($label);

14

15 show_all $w;

16

17 main Gtk;

--------------------------

第4行 载入主 GNOME 模块;这样会同时载入 GTK+ 模块

第8行 设置本次会话及注册本程序所需的所有东西,这里我们把程序的名称传给了 init 方法

第10行 创建主窗口;这是一个顶层的窗口,也就是该应用程序的根窗口

第12行 创建一个消息标签,包含文字""hello, world"";所有要放在窗口上的文字必须放在 Gtk::Label 对象中

第13行 此时,$label 对象什么事也没有做,也不知道该放在什么地方,所以这里我们使用window对象的 add 方法来加入这个对象

第15行 显示 window 对象,及其他所包含的对象,在这里,就是 label 对象,我们使用了window 对象的 show_all 方法,注意,该方法并不是真正的在屏幕上显示窗口,而是做一个初始的说明,

第17行 使用 GTK+ 的 main event loop 来运行,这里才是真正的开始画窗口出来,并且等待事件的发生.此后,程序的控制权就交给了 GTK+ 了,程序的运行取决于用户的行为了,而你的程序就处于被动状态(等待激活)了.


再来看看GNOME的版本

------------------------------------

1 #!/usr/bin/perl -w

2

3 use strict;

4 use Gnome;

5

6 my $NAME = ''Hello World'';

7

8 init Gnome $NAME;

9

10 my $app = new Gnome::App $NAME, $NAME;

11

12 my $label = new Gtk::Label ""Hello, world"";

13 $app->set_contents($label);

14

15 show_all $app;

16

17 main Gtk;

------------------------------------


大多数都一样,但改了几行:

第10行 原先只是创建一个 window 对象,而现在则是提高了一个层次,我们说这里已经创建了整个应用程序,我们把应用程序的名字两次传递给了 new 方法,第一次说明 window 对象的 title 的值;第二次则是在 GNOME 环境中注册该应用程序


第13行 为什么是 set_contents 而不是 add 了呢? 原因在于 GTK+ 在 window 中放置图形元素(widget)的方式基于容器(container)的思想,简单的放置,只允许你在 window 中放一个窗口小部件(widget),所幸的是,一些 widget 允许包含其他的 widget.


现在,你可能会发现,当你使用 close 按钮时,perl 程序并没有结束,而我们必须使用类似 ^C 的方式来结束运行;而使用 GNOME 时,GNOME 应用程序在收到window 对象的 close 消息时, GNOME 会给我们发送一个信号,但这不是真正的 UNIX 核心所发出的信号,而我们需要安装信号的处理句柄来干净的结束程序的运行,可以这样做:


------------------------------------

my $app = new Gnome::App $NAME, $NAME;

signal_connect $app ''delete_event'',

sub { Gtk->main_quit; return 0 };

------------------------------------


这里,我们把 delete_event 信号和一个匿名函数关联,也就是说,当程序接受到 Gnome 环境送来的 delete_event 信号时,触发执行该匿名函数,而该函数则调用标准的 main_quit 方法来结束 main loop, 最后真正的退出运行.

下面我们来加上菜单栏.前面已经说过,Gnome 构建于 Gtk+ 之上,它提供许多标准的东西使我们在写程序的时候更方便,更具可扩展性.下面的程序建立了一个标准的菜单栏:


------------------------------------

$app->create_menus(

{type => ''subtree'',

label => ''_File'',

subtree => [

{type => ''item'',

label => ''E_xit'',

pixmap_type => ''stock'',

pixmap_info => ''Menu_Quit''

}

]

},

{type => ''subtree'',

label => ''_Help'',

subtree => [

{type => ''item'',

label => ''_About...'',

pixmap_type => ''stock'',

pixmap_info => ''Menu_About''

}

]

}

);

------------------------------------


在这里,我们传递了一系列的匿名哈西结构给 create_menus 方法,每一个就是一个菜单项(tab),type 为 subtree 时说明该项具有子菜单;为 item 时说明该项为一个菜单内容;label 的值也就是菜单上显示的提示文字,而下划线后的字母则为键盘快捷键,如 _About 则说明按下 Alt-A 就激活该项;关键字 subtree 指定该项的子菜单的内容,是一个包含一系列匿名哈西菜单结构的匿名数组;子菜单项类型为 item 时,显示时使用一个图标作为按钮,在这里,我们使用 GNOME 图标库 stock ,使用关键字 pixmap_type 来指定;而 pixmap_info 所指定的值即为鼠标移到该图标按钮上时显示的提示文字.

原来你应该是用 perl hello.pl 的方式运行该程序的吧?那么现在再试试使用 LANG=fr_FR perl hello.pl ,有没有看到菜单文字被翻译成了法语? 再试试 pt_PT , de_DE , el_GR ,很神奇吧!

上面的程序只创建了菜单,但是还不能做些什么,那么看一下:


------------------------------------

{type => ''item'',

label => ''E_xit'',

pixmap_type => ''stock'',

pixmap_info => ''Menu_Quit'',

callback => sub {Gtk->main_quit; return 0 }

}

------------------------------------


现在,我们把退出程序时要做的事情封装在一个匿名函数里并作为 callback 的值,就这样简单!在 about 项里,则可以使用 callback=>&about_box ,另外创建一个自己的 about_box 函数:


------------------------------------

sub about_box {

my $about = new Gnome::About $NAME, ""v1.0"",

""(C) Simon Cozens, 2000"", [""Simon Cozens""],

""This program is released under the same terms as Perl itself"";

show $about;

}

------------------------------------


Gnome::About 类给我们提供了一个接口,我们只需将本应用程序的名字,版本号,版权信息,作者名字(使用匿名数组,因为可能有不只一个作者)等传递给它即可,最后使用 show 方法将之显现.运行时,你会看到点击 about 会弹出 about 信息窗口,含有 OK 按钮,点击该按钮则自动关闭该窗口.


一般的应用程序还有工具栏和状态栏,那么,与上面的类似,加入以下代码:


------------------------------------

$app->create_toolbar(

{

type => ''item'',

label => ''Exit'',

pixmap_type => ''stock'',

pixmap_info => ''Quit'',

hint => ""Click here to quit"",

callback => sub { Gtk->main_quit },

}, {

type => ''item'',

label => ''About...'',

pixmap_type => ''stock'',

pixmap_info => ''About'',

hint => ""More information about this app"",

callback => &about_box

}

);

------------------------------------


其中,hint 所指定的值即为鼠标移到该图标按钮上时显示的提示文字,接着是状态栏:


------------------------------------

my $bar = new Gnome::AppBar 0,1,""user"" ;

$bar->set_status("" Welcome "");

$app->set_statusbar( $bar );

------------------------------------


先创建一个 AppBar 对象,然后使用 set_status 方法来初始化状态栏中显示的内容,然后使用 app 对象的 set_statusbar 方法来显示它.


好啦,现在来完整的看一下这个程序:

------------------------------------

#!/usr/bin/perl -w

use strict;

use Gnome;

my $NAME = ''Hello World'';

init Gnome $NAME;

my $app = new Gnome::App $NAME, $NAME;

signal_connect $app ''delete_event'', sub { Gtk->main_quit; return 0 };

$app->create_menus(

{type => ''subtree'',

label => ''_File'',

subtree => [

{type => ''item'',

label => ''E_xit'',

pixmap_type => ''stock'',

pixmap_info => ''Menu_Quit'',

callback => sub { Gtk->main_quit; return 0 }

}

]

},

{type => ''subtree'',

label => ''_Help'',

subtree => [

{type => ''item'',

label => ''_About...'',

pixmap_type => ''stock'',

pixmap_info => ''Menu_About'',

callback => &about_box

}

]

}

);

$app->create_toolbar(

{

type => ''item'',

label => ''Exit'',

pixmap_type => ''stock'',

pixmap_info => ''Quit'',

hint => ""Click here to quit"",

callback => sub { Gtk->main_quit },

}, {

type => ''item'',

label => ''About...'',

pixmap_type => ''stock'',

pixmap_info => ''About'',

hint => ""More information about this app"",

callback => &about_box

}

);

my $label = new Gtk::Label ""Hello, world"";

$app->set_contents($label);

my $bar = new Gnome::AppBar 0,1,""user"" ;

$bar->set_status("" Welcome "");

$app->set_statusbar( $bar );

show_all $app;

main Gtk;

sub about_box {

my $about = new Gnome::About $NAME, ""v1.0"",

""(C) Simon Cozens, 2000"", [""Simon Cozens""],

""This program is released under the same terms as Perl itself"";

show $about;

}

------------------------------------


到这里,我们已经写出了一个十分简单的基于 perl 的 Gnome 环境下的应用程序,很简单吧?下次,我再来讲解更进一步的内容(如何使用其他图形元素等).