Chinaunix首页 | 论坛 | 博客
  • 博客访问: 447883
  • 博文数量: 145
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1060
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-22 11:52
个人简介

专注计算机技术: Linux Android 云计算 虚拟化 网络

文章分类

全部博文(145)

文章存档

2016年(3)

2015年(21)

2014年(75)

2013年(46)

我的朋友

分类: PERL

2014-01-26 16:27:11

Adam Cormany, UNIX 系统工程师, Scientific Games Corporation

2008 年 6 月 30 日

尽管基于 Perl 的 Web 界面存在局限性,但 Perl 仍是最常用的 Web 开发语言之一。在 Shell 脚本、Perl 或其他语言方面有编程经验的 UNIX? 用户可通过使用 Perl/Tk 模块为基于 Perl 的 Web 界面带来新的生机。

引言

Perl 语言经常由 IBM? AIX? 操作系统管理员和开发人员使用,几乎每个成功的网站和大多数 AIX 系统上都使用了该语言。尽管 Perl 脚本的功能非常强大,但它产生的 Web 界面却缺少图形化前端,用户必须键入信息,而不能使用鼠标,对于客户来说,这一点非常不尽人意。随着 Perl 中 Tk 模块的引入,此问题已得到解决。管理员或开发人员可以利用 Tk 模块快速为其 Perl 脚本带来新的生机,从而满足客户对 X11 产品的需要。

小部件

正如在本系列文章的第 1 部分中所讨论的,可以将小部件定义为执行特定功能的图形对象。Perl/Tk 模块中的任何图形对象都可以视为一个小部件。对于 GUI 应用程序而言,按钮、文本、框架和滚动条都是小部件。本文是该系列文章的第三部分,将讨论诸如 DirTree、LabEntry、LabFrame 和 Table 等小部件。

DirTree

编程的一个主要可视部分是如何处理文件和目录搜索。对此难题的一个解决方案是使用 DirTree 小部件。

使用 Perl/Tk 模块创建目录清单是非常简单的:

#!/usr/bin/perl –w
#create a directory listing with DirTree

use Tk;
use strict;
use Tk::DirTree;
use Cwd;

my $mw = MainWindow->new;
$mw->geometry("300x400");
$mw->title("DirTree Example");

my $CWD = Cwd::cwd();

my $DIR_TREE = $mw->Scrolled('DirTree',
                             -scrollbars => "osoe",
                             -width => 30,
                             -height => 25,
                             -exportselection => 1,
                             -browsecmd => sub {$CWD = shift},
                             -command   => \&show_cwd)->pack(-fill => "both",
                                                             -expand => 1);

$DIR_TREE->chdir($CWD);

my $button_frame = $mw->Frame()->pack(-side => "bottom");
$button_frame->Button(-text => "Ok",
                      -command => \&show_cwd)->pack(-side => "left");
$button_frame->Button(-text => "Exit",
                      -command => sub{exit})->pack(-side => "left");

sub show_cwd {
  $mw->messageBox(-message => "Directory Selected: $CWD", -type => "ok");
}

MainLoop;

执行此脚本将生成如图 1 和 2 所示的 GUI 应用程序:


图 1. DirTree 小部件示例
DirTree 小部件示例

图 2. 显示选定的目录
显示选定的目录

下面让我们分析一下该脚本。

为了回顾一下本系列第 1 部分和第 2 部分中讨论的内容,下面仅对此代码的第一部分讨论一次,除非后面的示例对其进行了更改。此代码行的第一部分 (/usr/bin/perl) 定义 Perl 可执行文件在计算机上的驻留位置,并指示计算机使用该 Perl 可执行文件副本来执行文件 multiple_windows_at_once-demo.pl:

#!/usr/bin/perl -w

此命令行的第二部分 (-w) 是 Perl 中的一个重要工具。它支持在执行脚本时发出警告,通知最终用户可能发现的任何错误。

在执行期间不应计算的注释和文本前面加上了一个 # 号:

#create a directory listing with DirTree

为了使 Perl 脚本使用 Tk 模块,必须包含该模块;因此添加了 use Tk 语句。将 use strict 语句添加到 Perl 脚本还有助于发现任何可能的输入或逻辑错误:

use Tk;
use strict;

要使用 DirTree 小部件,必须将其包含在 Perl 脚本中,因为它不是基本 Perl 模块中的普通小部件。第二个包含是 Cwd。使用此包含语句,该脚本就可以查找和存储 CWD(或当前工作目录):

use Tk::DirTree;
use Cwd;

要创建应用程序的主窗口,可以使用 MainWindow,并将其分配给 $mw。$mw 用作所创建的所有其他小部件的父窗口(本文将对此作进一步的讨论):

my $mw = MainWindow->new;

将主窗口大小设置为 300x400,并将主窗口标题设置为 DirTree Example

$mw->geometry("300x400");
$mw->title("DirTree Example");

查找 CWD,并将其存储在名为 $CWD 的变量中:

my $CWD = Cwd::cwd();

创建一个可滚动的目录树。browsecmd 选项在最终用户每次选择某个目录时重置 $CWD。如果最终用户在某个目录上双击或按 Enter 键,则 command 选项将执行子例程 show_cmd:

my $DIR_TREE = $mw->Scrolled('DirTree',
                             -scrollbars => "osoe",
                             -width => 30,
                             -height => 25,
                             -exportselection => 1,
                             -browsecmd => sub {$CWD = shift},
                             -command   => \&show_cwd)->pack(-fill => "both",
                                                             -expand => 1);

刷新显示了用户的 CWD 的目录树:

$DIR_TREE->chdir($CWD);

创建一个框架,并在其中放置两个按钮。标签为“OK”的第一个按钮执行子例程 show_cmd;第二个按钮退出该脚本:

my $button_frame = $mw->Frame()->pack(-side => "bottom");
$button_frame->Button(-text => "Ok",
                      -command => \&show_cwd)->pack(-side => "left");
$button_frame->Button(-text => "Exit",
                      -command => sub{exit})->pack(-side => "left");

执行子例程 show_cmd 时,将显示一个 messageBox 小部件,其中显示了用户的 CWD:

sub show_cwd {
  $mw->messageBox(-message => "Directory Selected: $CWD", -type => "ok");
}

在执行 MainLoop 之前,可以读取、定义和随时执行该脚本中的所有内容。然后,在调用 MainLoop 时,将执行先前读取的所有功能和数据,并显示 GUI:

MainLoop;

LabEntry

许多 GUI 应用程序需要来自最终用户的手动输入。显示说明和请求输入的一种方法是使用 Label 和 Entry 小部件(已在本系列的第 1 部分中进行了讨论)。另一种方法是使用 LabEntry 小部件。LabEntry 将 Label、Entry 和 Frame 小部件组合为单个易于使用的小部件:

#!/usr/bin/perl -w

use Tk;
use Tk::LabEntry;
use strict;

my $mw = MainWindow->new;
$mw->geometry("300x100");
$mw->title("LabEntry Example");

my $name = "";
$mw->LabEntry(-label => "Enter your name: ",
              -labelPack => [ -side => "left" ],
              -textvariable => \$name)->pack();

my $button_frame = $mw->Frame()->pack(-side => "bottom");
$button_frame->Button(-text => "Ok",
                      -command => \&show_greeting)->pack(-side => "left");
$button_frame->Button(-text => "Exit",
                      -command => sub{exit})->pack(-side => "left");

sub show_greeting {
  my $msg = "Who are you?";
  if ($name ne "") { $msg = "Nice to meet you $name!"; }
  $mw->messageBox(-message => "$msg\n", -type => "ok");
}

MainLoop;

执行此脚本将生成如图 3 和 4 所示的 GUI 应用程序:


图 3. LabEntry 小部件示例
LabEntry 小部件示例

图 4. LabEntry 小部件的结果
LabEntry 小部件的结果

下面让我们分析一下该脚本。

与前一个使用 DirTree 的示例一样,需要包含 LabEntry 小部件。如果没有包含该小部件,Perl 脚本将不知道如何解释或执行 LabEntry 小部件:

use Tk::LabEntry;

定义一个名为 $name 的变量,并将其值设置为 NULL 或设置为空。在定义变量之后,使用标签 Enter your name: 创建 LabEntry 小部件,对输入框左侧的标签打包,并将输入的值分配给变量 $name:

my $name = "";
$mw->LabEntry(-label => "Enter your name: ",
              -labelPack => [ -side => "left" ],
              -textvariable => \$name)->pack();


创建一个框架,并在其中包括两个 Button 小部件。标签为“OK”的第一个按钮执行子例程 show_greeting;第二个按钮退出该脚本:

my $button_frame = $mw->Frame()->pack(-side => "bottom");
$button_frame->Button(-text => "Ok",
                      -command => \&show_greeting)->pack(-side => "left");
$button_frame->Button(-text => "Exit",
                      -command => sub{exit})->pack(-side => "left");

单击 OK 按钮时,将执行子例程 show_greeting。变量 $msg 定义了值“Who are you?”。为该变量定义此值是为了以防最终用户忘记在 LabEntry 中输入其姓名。如果用户忘记,则变量 $name 仍然设置为 NULL。如果用户输入了姓名,则为 $msg 设置值“Nice to meet you $name!”,在下一行代码中可以看到这点。最后,向用户显示 messageBox 小部件,无论是向他致意还是告诉他该程序不知道他是谁:

sub show_greeting {
  my $msg = "Who are you?";
  if ($name ne "") { $msg = "Nice to meet you $name!"; }
  $mw->messageBox(-message => "$msg\n", -type => "ok");
}

LabFrame

本系列文章中到处都使用到了 Frame 小部件。Frames 用于组织其他小部件,使应用程序看起来更整洁和更有条理。与框架配套的一个便利的小部件是 LabFrame。使用 LabFrame 小部件,您只需做很少的工作即可将标签放在框架上或框架旁边:

#!/usr/bin/perl -w

use Tk;
use Tk::LabFrame;
use strict;

my $mw = MainWindow->new;
$mw->geometry("300x200");
$mw->title("LabFrame Example");

my $labeled_frame1 = $mw->LabFrame(-label => "Caption Across Top of Frame",
                                   -labelside => "acrosstop")->pack();

my $labeled_frame2 = $mw->LabFrame(-label => "Caption Below Frame",
                                   -labelside => "bottom")->pack(-fill => "x");

$labeled_frame1->Label(-text => "Inside Frame #1")->pack();
$labeled_frame2->Label(-text => "Inside Frame #2")->pack();

my $button_frame = $mw->Frame()->pack(-side => "bottom");
$button_frame->Button(-text => "Exit",
                      -command => sub{exit})->pack();

MainLoop;


执行此脚本将生成如图 5 所示的 GUI 应用程序。


图 5. LabFrame 小部件示例
LabFrame 小部件示例

下面让我们分析一下该脚本。

LabFrame 与本文前面的小部件示例没有什么不同,并且需要包含在脚本中:

use Tk::LabFrame;

创建一个框架,将其标签设置为 Caption Across Top of Frame。要按照该标题所暗示的那样在框架顶部放置标题,您必须为选项 labelside 配置值“acrosstop”,从而配置 LabFrame 小部件:

my $labeled_frame1 = $mw->LabFrame(-label => "Caption Across Top of Frame",
                                   -labelside => "acrosstop")->pack();

创建第二个 LabFrame 小部件,但不是将标题放在框架顶部,而是通过将选项 labelside 设置为“bottom”,从而在框架下面放置标签 Caption Below Frame

my $labeled_frame2 = $mw->LabFrame(-label => "Caption Below Frame",
                                   -labelside => "bottom")->pack(-fill => "x");

为了演示 LabFrame 中的小部件,可以在父 LabFrame 小部件旁边创建两个 Label 小部件:

$labeled_frame1->Label(-text => "Inside Frame #1")->pack();
$labeled_frame2->Label(-text => "Inside Frame #2")->pack();

Table

Table 小部件是对 Perl 脚本的极大增强。此小部件创建小部件的二维表。与显示未组织的长数据清单不同,您可以使用表:

#!/usr/bin/perl -w

use Tk;
use Tk::Table;
use strict;

my $mw = MainWindow->new;
$mw->geometry("475x125");
$mw->resizable(0,0);
$mw->title("Table Example");

my $table_frame = $mw->Frame()->pack();
my $table = $table_frame->Table(-columns => 8,
                                -rows => 4,
                                -fixedrows => 1,
                                -scrollbars => 'oe',
                                -relief => 'raised');

foreach my $col (1 .. 8)
{
  my $tmp_label = $table->Label(-text => "COL " . $col, -width => 8, -relief =>'raised');
  $table->put(0, $col, $tmp_label);
}

foreach my $row (1 .. 8)
{
  foreach my $col (1 .. 8)
  {
    my $tmp_label = $table->Label(-text => $row . "," . $col,
                                  -padx => 2,
                                  -anchor => 'w',
                                  -background => 'white',
                                  -relief => "groove");
    $table->put($row, $col, $tmp_label);
  }
}
$table->pack();

my $button_frame = $mw->Frame( -borderwidth => 4 )->pack();
$button_frame->Button(-text => "Exit", -command => sub {exit})->pack();

MainLoop;


执行此脚本将生成如图 6 所示的 GUI 应用程序。


图 6. Table 小部件示例
Table 小部件示例

下面让我们分析一下该脚本。

您一定猜到了!必须包含另一个新的小部件,以便让 Perl 知道如何处理 Table 小部件:

use Tk::Table;

在前面的示例中,最终用户可以调整应用程序的窗口大小。此脚本禁止用户调整窗口的大小:

$mw->resizable(0,0);

创建一个框架来包含新的表。然后创建 Table 小部件,其中显示八列和四行:

my $table_frame = $mw->Frame()->pack();
my $table = $table_frame->Table(-columns => 8,
                                -rows => 4,
                                -fixedrows => 1,
                                -scrollbars => 'oe',
                                -relief => 'raised');

要在表中放置数据,可以使用 put 操作。循环八次,将文本“COL”添加到当前列的第一(0)行:

foreach my $col (1 .. 8)
{
  my $tmp_label = $table->Label(-text => "COL " . $col, -width => 8, -relief =>'raised');
  $table->put(0, $col, $tmp_label);
}

现在已经创建了标题,下面将把坐标放在各个单元格中。同样,使用 put 操作,循环遍历每行和每列并分配单元格的文本。然后,对完成后的表进行打包 (pack):

foreach my $row (1 .. 8)
{
  foreach my $col (1 .. 8)
  {
    my $tmp_label = $table->Label(-text => $row . "," . $col,
                                  -padx => 2,
                                  -anchor => 'w',
                                  -background => 'white',
                                  -relief => "groove");
    $table->put($row, $col, $tmp_label);
  }
}
$table->pack();

Canvas

Canvas 是 Perl/Tk 模块中的一个非常有用的绘图工具。使用此小部件,用户可以绘制和操作不同的形状和对象,例如直线、椭圆、矩形和多边形:

#!/usr/bin/perl -w

use Tk;
use strict;

my $mw = MainWindow->new;
$mw->geometry("400x400");
$mw->title("Canvas Example");

my $canvas = $mw->Canvas(-relief => "sunken", -background => "blue");

$canvas->createLine(2, 3, 350, 100, -width => 10, -fill => "black");
$canvas->createLine(120, 220, 450, 200, -fill => "red");
$canvas->createOval(30, 80, 100, 150, -fill => "yellow");
$canvas->createRectangle(50, 20, 100, 50, -fill => "cyan");
$canvas->createArc(40, 40, 200, 200, -fill => "green");
$canvas->createPolygon(350, 120, 190, 160, 250, 120, -fill => "white");

$canvas->pack();

$mw->Button(-text => 'Exit', -command => sub {exit})->pack();;

MainLoop;

执行此脚本将生成如图 7 所示的 GUI 应用程序。


图 7. Canvas 小部件示例
Canvas 小部件示例

下面让我们分析一下该脚本。

以下代码创建 Canvas 小部件:

my $canvas = $mw->Canvas(-relief => "sunken", -background => "blue");

创建一条宽度为 10 的黑线,并将其从 (2, 3) 绘制到 (350, 100)。在处理 Canvas 小部件中的对象和形状时,第一组数值是坐标。最适合使用公式 (x1, y1, x2, y2, ....) 来查看某个对象:

$canvas->createLine(2, 3, 350, 100, -width => 10, -fill => "black");
$canvas->createLine(120, 220, 450, 200, -fill => "red");

在 Canvas 小部件上创建一个从 (30, 80) 到 (100, 150) 的黄色椭圆:

$canvas->createOval(30, 80, 100, 150, -fill => "yellow");

在 Canvas 小部件上创建一个从 (50, 20) 到 (100, 50) 的青色矩形:

$canvas->createRectangle(50, 20, 100, 50, -fill => "cyan");

在 Canvas 小部件上创建一个从 (40, 40) 到 (200, 200) 的绿色弧形:

$canvas->createArc(40, 40, 200, 200, -fill => "green");

在 Canvas 小部件上创建一个从 (350, 120) 到 (190, 160) 和 (250, 120) 的白色多边形:

$canvas->createPolygon(350, 120, 190, 160, 250, 120, -fill => "white");

在创建所有对象之后,与以前一样,对该小部件打包:

$canvas->pack();








结束语

将带有 Perl/Tk 模块的 Perl 引入 AIX 环境可以让开发人员、管理员、客户和最终用户受益。客户起初觉得很枯燥的脚本,可以增强为具有专业外观的 GUI 应用程序。熟悉这些小部件可能需要一些时间,但是,您掌握了这些技术之后,就会感到付出精力确实值得!

阅读(3370) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~