Xforms 与 Perl 结合
正如您在近期《Linux Journal》的各种期刊中看到的那样,Xforms 库允许您使用简单直观的 API 为您的 C 或 C++ 程序添加强大的 GUI。Xforms GUI 的功能和优雅性可与 Motif 相媲美,但如果用于非商业用途,Xforms 库是免费的。感谢 Martin Bartlett (martin@nitram.demon.co.uk),Xforms 的 GUI 可以从 Perl 脚本中使用,以运行复杂的图形应用程序或提供简单的“请稍候,正在加载”状态栏,这样用户就不会因等待而感到无聊(见图 1)。本文将讨论如何安装 Xforms4Perl(0.5 版本)以及如何使用它编写一个简单的地址簿程序。
为了安装 Xforms4Perl,首先您必须安装以下组件
Perl 版本 5.003(或更高版本),编译时需支持动态加载库。
XForms 库,版本 0.86 或 0.88,可在 http://bragg.phys.uwm.edu/xforms 找到。
接下来您需要获取 Xforms4Perl 的源代码,您可以从作者的主要站点 ftp://ftp.demon.co.uk/pub/perl/perl/,或任何 CPAN 镜像站点的 /authors/Martin_Bartlett/ 目录下获取。您也可以从 ftp://ftp.redhat.com/pub/contrib 或 CPAN 获取 RPM,并跳过接下来的几个章节。
下载 Xforms4Perl 后,使用 tar zxvf Xforms4Perl-0.8.4tgz 将其解压缩到方便的目录(例如,/usr/local/src)。此命令将创建子目录 Xforms4Perl-0.8.4。
Xforms 支持 OpenGL,如果您想从 Xforms4Perl 访问它,或者如果您需要修改一些默认路径或库位置,您需要编辑位于子目录 X11/XEvent、X11/XFontStruct 和 X11/Xforms 中的 Makefile.PL 文件。
然后进入 X11 子目录并执行以下操作
键入 perl Makefile.PL。
键入 make。
键入 make install(以 root 用户身份)。
将 fd2Perl 复制到 PATH 环境变量包含的目录中。
安装完成后,您就可以开始编写使用 Xforms 的 Perl 代码了。您还可以查看 PerlXForms 附带的一些演示,例如作者的 XFtool,它类似于 Microsoft Office 工具栏。本文的其余部分假设您已经对 Xforms 和 Perl 有了基本的了解,尽管它们都非常易于使用,您可能只需看几个示例就能掌握它们。
为了帮助解释如何使用 Xforms4Perl 库,我将以从头到尾开发一个简单的电话簿应用程序为例。最好的起点是 Xforms 库附带的 fdesign 应用程序。它允许您可视化地构建应用程序的组件。您无需费力计算按钮应该是 33x55 像素还是 30x50 像素,只需按您想要的方式绘制它,fdesign 就会处理所有的数字和细节。为了使事情更简单,fdesign 能够输出 Perl 代码(感谢上面提到的 fd2Perl 脚本)。我们以 fdesign -perl 的方式调用 fdesign,并创建一个名为“list”的新表单(见图 2)。
首先,我们添加一个名为 browser 的对象,电话簿姓名条目将在其中建立索引。在属性部分下,我们指定我们希望它是一个 HOLD_BROWSER,这允许从浏览器中选择的项目在选择后保持突出显示。然后我们给它一个明显的名称,例如 browser,并设置一个回调函数。当浏览器中发生某些操作时,将执行此函数——使用回调函数在 GUI 编程中相当标准。我们随机选择名称 browser_clicked 作为回调函数。
现在我们添加五个文本输入字段,所有字段都具有相同的回调函数,名为 data_change。这些字段将显示电话簿条目中的个人信息,并且也是用户可以进行数据修改的位置。这些字段已标记,并在属性部分中给出了以下名称
接下来,我们添加四个按钮。这里可以使用下拉菜单,但四个按钮不会使界面显得杂乱,并且比菜单更容易访问。这些按钮标记为“Quit!”、“Clear”、“Update”和“Delete Entry”。Quit 按钮的用途应该是显而易见的。“Clear”按钮用于清除文本输入字段,“Update”按钮用于保存或更新文本输入字段中的内容,“Delete Entry”按钮用于从浏览器列表中删除选定的条目。这些按钮都具有回调,如下所示。
最后,我们可以添加一个标题,例如“PhoneBook”或任何其他内容来改善外观,这使用 fdesign 非常简单——您只需放置它即可完成。我还认为给一些按钮添加阴影效果可能不错,这是从相应按钮的属性菜单完成的。
现在我们已经完成了应用程序的设计,我们可以将其保存为名为 pbook 的文件。此操作会生成四个(或更多,取决于您的设置)文件。我们感兴趣的是名为 pbook.pl 的文件 (列表 1)。如果我们想修改我们的设计,.pl 文件将被重新生成;因此,我们不应该修改此文件,因为对其所做的任何更改都将丢失。相反,在我们的代码中,我们需要 require 该文件来为我们设置表单。
对于要使用 Xforms4Perl 的 Perl 脚本,您只需添加以下行
use X11::Xforms;
到您的 Perl 脚本的顶部。此命令动态加载所有需要加载的内容。如果您想访问 XFontStruct 或 XEvent 结构,那么您还需要添加 use X11::XFontStruct 或 use X11::XEvent。在执行任何涉及 Xforms 库的操作之前,您必须调用一个函数,以便 Xforms 可以初始化其所有内部变量等。这可以通过调用来实现
fl_initialize('Phone Book');并为其提供您想要的应用程序的标题。您可以通过调用子例程来设置您需要的所有表单,例如
create_form_list();由 fdesign 和 fd2perl 生成的那些。然后,添加您需要的任何初始化代码。例如,如果您使用 fdesign 创建一个“滑块”,并且需要根据一些输入设置滑块的值范围,您将需要使用正确的参数调用 fl_set_slider_bounds。完成配置后,您就可以向用户显示表单了。为此,请进行调用
fl_show_form($list,FL_PLACE_FREE,FL_FULLBORDER, "Phone Book");还有一些命令可以使表单消失,因此处理多个表单非常容易。您提供给 fl_show_form 的选项包括您希望显示的特定表单(记住我们将其称为“list”)、窗口管理器的选项和一个标题。一旦一切设置完毕,并且您已准备好让用户与 GUI 交互,您就可以继续调用函数 fl_do_forms。因此,显示此表单所需的最少代码量是
#!/usr/local/bin/perl use X11::Xforms; require "pbook.pl"; fl_initialize('Phone Book'); create_form_list(); fl_show_form($list, FL_PLACE_FREE, FL_FULLBORDER, 'Phone Book'); while(1) {fl_do_forms};用户与 GUI 的实际交互是通过回调函数完成的。请记住,这代表了使用 Xforms4Perl 的基本模式的最基本要素,还有许多其他使用库的方法。有关更高级的方法,应查阅 Xforms 手册。
让我们看看我们的电话簿程序现在是如何组合在一起的。完整的列表可以在 列表 2 中找到。首先,查看整个主例程。除了上面的列表之外,我们还添加了对两个子例程的调用,以在用 fl_show_form 函数显示浏览器之前初始化浏览器。
load_data(); update_browser()
如您所见,程序的大部分是在子例程中处理的。首先,我们加载库并初始化程序。调用 create_form_list 设置我们使用 fdesign 组合在一起的表单。调用 load_data 从用户主目录中名为 .pbook 的文件加载数据。此文件的格式已任意设置为每行包含一个电话簿条目,数据用冒号分隔。(假设用户永远不会在任何条目中使用冒号。见图 3。).pbook 中的一个示例条目(一行)如下所示
Suhad:414 555-1234:2014 S 102nd St:Milwaukee, WI 53227:sniazi@ucsd.edu
现在数据已加载,update_browser 调用清除浏览器并将新加载的名称添加到浏览器列表。为了向用户显示电话簿,我们调用 fl_show_form,然后循环执行 fl_do_forms 以便 Xforms 接管。
与用户的其余交互通过回调处理,其中包括添加或更新条目、保存新条目、显示信息和退出应用程序。完整代码如列表 2 所示,考虑到 Xforms 的详细函数名称,回调如何协同工作是显而易见的。例如,fl_get_input 从输入字段获取数据,fl_set_input 将其设置为某个值。为了更好地了解所有可用的函数,您可以打印出 Xforms 附带的 200 页手册;它是一个非常宝贵的参考。
虽然应该很容易猜到列表 2 中的代码是做什么的,但我想提及和澄清几件事。首先,当数据加载时,它保存在名为 $DATA 的数据结构中,该结构是指向匿名哈希的指针,其中包含地址簿中人员的姓名。反过来,每个姓名都是指向另一个匿名哈希的指针,其中包含电话号码、地址等。例如,要访问 Tom 的电话号码,您可以使用 $DATA->{'Tom'}->{pnumber}。因为我们选择使用这种方法来处理数据的存储和组织,所以我们遇到了一个小问题。如果我们修改条目的名称(即,将 Tom 更改为 Tommy),程序会认为它正在处理一个新条目(因为哈希的键已更改),因此,创建了两个条目:一个基于名称 Tom,另一个基于名称 Tommy。我将其作为练习留给读者,让他们找到解决此问题的方法。
大多数子例程使用 fl_set_input 或 fl_get_input 调用来操作您看到的数据。唯一复杂的调用是
$name=fl_get_browser_line($browser, fl_get_browser($browser));
此调用用于确定浏览器中突出显示的名称。例如,在图 2 中,突出显示的名称是 Suhad。为了做到这一点,我们需要给 fl_get_browser 条目出现的行号。为了获得该数字,我们调用 fl_get_browser_line,它返回当前突出显示的行号。
另一件需要注意的是,这个电话簿没有“保存”按钮,而是假设您不会犯错。因此,每次您单击“Update”按钮或“Delete Entry”按钮时,它都会保存数据。上次保存文件的备份将保留为 .pbook.bak,以防出现问题,但用户必须自行恢复备份——这不是自动的。
本文引用的所有列表都可以通过匿名下载在文件 ftp.linuxjournal.com/pub/lj/listings/issue55/2024.tgz 中获得。
Reza Naima (reza@reza.net) 去年在思科系统公司工作,负责 Web 服务器安全。他的职责包括确保任何部署的代码都是安全的、制定安全标准和编写自动化应用程序。他刚离开思科,开始为期 3.5 个月的环球旅行,将于 9 月中旬返回。