了解 Perl/Tk 模块,第 2 部分: 中级小部件

来源:岁月联盟 编辑:zhu 时间:2009-03-05

  引言

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

  了解小部件

  正如在第 1 部分中所讨论的, 小部件 是执行特定功能的图形对象。Perl/Tk 模块中的任何图形对象都可以视为一个小部件。在 GUI 应用程序中,按钮、文本、框架和滚动条全都是小部件。此第二篇文章将讨论如下小部件:

  Radiobutton

  Checkbutton

  Menu

  Menubutton

  Scrollbar

  包装小部件

  pack 是最常用的功能之一,同时也是最复杂的方法之一。pack 功能是 Perl/Tk 模块中的几何或布置管理器。当开发人员定义某个小部件时,它只是经过了定义。在几何管理器适当分配空间之前,小部件不会显示出来——这就是 pack 发挥作用的地方。pack 功能计算小部件的父级对象上分配的空间并显示小部件。

  创建多个窗口

  取决于最终用户的需要,应用程序可能需要多个窗口。创建多个窗口非常简单。它扩展了第 1 部分中使用的方法。要回答的第一个问题在于,应用程序应该同时创建并显示窗口,还是应该由用户的操作触发新窗口的创建和显示。本部分将同时讨论这两种方法。创建一个同时显示多个窗口的应用程序是创建单个窗口的延伸,只是另外添加了 TopLevel 小部件:#!/usr/bin/perl -w
# Create multiple windows at once
   
use Tk;
use strict;
    
my $mw = MainWindow->new;
$mw->geometry("200x100");
$mw->title("Multiple Windows Test");
    
my $subwin1 = $mw->Toplevel;
$subwin1->title("Sub Window #1");
    
my $subwin2 = $mw->Toplevel;
$subwin2->title("Sub Window #2");
    
MainLoop;

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

  图 1. 一次打开多个窗口的示例

了解 Perl/Tk 模块,第 2 部分: 中级小部件

  本文回顾了一遍第一部分中的代码,以便复习本系列的第 1 部分中讨论的内容。此代码行的第一部分 (/usr/bin/perl) 定义 Perl 可执行文件在计算机上的驻留位置,并指示计算机使用该 Perl 可执行文件副本来执行文件 multiple_windows_at_once-demo.pl:#!/usr/bin/perl -w

  此代码行的第二部分 (-w) 是 Perl 中的一个重要工具:它支持在执行脚本时发出警告,通知最终用户可能发现的任何错误。在执行时不进行求值的注释和文本前面加有一个磅字符 (#)。例如:# Create multiple windows at once

  为了使 Perl 脚本使用 Tk 模块,必须包括该模块:因此要添加 use Tk 代码。例如:use Tk;
use strict;

  向 Perl 脚本添加 use strict 语句可帮助查找输入错误和逻辑错误。要创建应用程序的主窗口,可以使用 MainWindow,并将其分配给 $mw。例如:my $mw = MainWindow->new;

  $mw 充当所有其他小部件的父窗口,本文将对此作进一步的讨论。将主窗口大小设置为 200x100,并将主窗口标题设置为 Multiple Windows Test。例如:$mw->geometry("200x100");
$mw->title("Multiple Windows Test");

  要在应用程序中创建附加窗口,可以使用 TopLevel 并将其分配给 $subwin1。例如:my $subwin1 = $mw->Toplevel;
$subwin1->title("Sub Window #1");

  与创建第一个附加窗口类似,创建另一个窗口并将其分配给 $subwin2。例如:my $subwin2 = $mw->Toplevel;
$subwin2->title("Sub Window #2");

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

  创建一个应用程序,并让该应用程序显示由用户触发的附加窗口,这同样是非常容易的。例如:#!/usr/bin/perl -w
# Create a sub window at the request of the user
use Tk;
use strict;
my $mw = MainWindow->new;
$mw->geometry("400x100");
$mw->title("Multiple Windows Test");
my $button1 = $mw->Button(-text => "Open new window",
             -command => &button1_sub)->pack(-side => "top");
$mw->Button(-text => "Exit", -command => sub{exit})->pack();
sub button1_sub {
 my $subwin1 = $mw->Toplevel;
 $subwin1->geometry("300x150");
 $subwin1->title("Sub Window #1");
 my $subwin_button = $subwin1->Button(-text => "Close window",
                    -command => [$subwin1 => 'destroy'])->pack();
}
MainLoop;

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

  图 2. 单独打开多个窗口的示例

了解 Perl/Tk 模块,第 2 部分: 中级小部件

  当此脚本执行时,将仅显示主窗口。但是,单击 Open new window 按钮将创建并显示子窗口(请参见图 3)。

  图 3. 打开的子窗口

了解 Perl/Tk 模块,第 2 部分: 中级小部件

  首先,创建一个标签为 Open new window 的按钮,并将其功能分配给子例程 button1_sub。同时创建一个 Exit 按钮,此按钮执行退出 Perl 脚本的子例程。例如:my $button1 = $mw->Button(-text => "Open new window",
             -command => &button1_sub)->pack(-side => "top");
$mw->Button(-text => "Exit", -command => sub{exit})->pack();

  button1_sub 子例程创建一个新窗口,其中具有设置大小和标题的 TopLevel 小部件。它还创建一个 Close Window 按钮,此按钮允许用户销毁子窗口。例如:sub button1_sub {
 my $subwin1 = $mw->Toplevel;
 $subwin1->geometry("300x150");
 $subwin1->title("Sub Window #1");
 my $subwin_button = $subwin1->Button(-text => "Close window",
                    -command => [$subwin1 => 'destroy'])->pack();
}

  使用中级小部件

  本部分讨论中级小部件,这一部分的讨论是第 1 部分中讨论的入门级小部件的延续。这些中级小部件包括 radiobutton、checkbutton、menu、menubutton 和 scrollbar 小部件。

  Radiobutton

  radiobutton 小部件显示一个或多个单选按钮;用户必须在按钮之间做出决定。下面的示例演示如何将 radiobutton 小部件引入应用程序。#!/usr/bin/perl -w
# create radio buttons
use Tk;
use strict;
my $mw = MainWindow->new;
$mw->geometry("300x100");
$mw->title("Radio Button Test");
my $color = "Red";
my $radio_frame = $mw->Frame()->pack(-side => "top");
$radio_frame->Label(-text=>"My favorite primary color is ")->pack(-side => "left");
my $radio_blue = $radio_frame->Radiobutton(-text => "Blue", -value => "Blue",
                      -variable=> $color)->pack(-side => "right");
my $radio_yellow = $radio_frame->Radiobutton(-text => "Yellow", -value => "Yellow",
                       -variable=> $color)->pack(-side => "right");
my $radio_red = $radio_frame->Radiobutton(-text => "Red", -value => "Red",
                     -variable=> $color)->pack(-side => "right");
my $button_frame = $mw->Frame()->pack(-side => "bottom");
my $button_color = $button_frame->Button(-text => "OK",
                     -command => &color_sub)->pack(-side => "left");
my $button_exit = $button_frame->Button(-text => "Exit",
                    -command => sub{exit})->pack(-side => "right");
sub color_sub {
 $mw->messageBox(-message => "You selected $color!", -type => "ok");
}
MainLoop;

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

  图 4. radiobutton 小部件示例

了解 Perl/Tk 模块,第 2 部分: 中级小部件

  您将首先定义变量 $color,并将其值设置为“Red”:my $color = "Red";

  创建一个框架来容纳单选按钮和标签可以为小部件提供整洁、对齐和专业的外观。创建一个 label 小部件以允许用户了解程序预期用户提供的输入。例如:my $radio_frame = $mw->Frame()->pack(-side => "top");
$radio_frame->Label(-text=>"My favorite primary color is ")->pack(-side => "left");
my $radio_blue = $radio_frame->Radiobutton(-text => "Blue", -value => "Blue",
                      -variable=> $color)->pack(-side => "right");
my $radio_yellow = $radio_frame->Radiobutton(-text => "Yellow", -value => "Yellow",
                       -variable=> $color)->pack(-side => "right");
my $radio_red = $radio_frame->Radiobutton(-text => "Red", -value => "Red",
                     -variable=> $color)->pack(-side => "right");

  创建三个 radiobutton 小部件,并将它们分配给预定义的变量 $color。每个单选按钮都具有文本和一个指定为某种颜色的值。由于为变量 $color 定义了值“Red”,因此 $radio_red 小部件是缺省值,并设置为 true。现在添加第二个框架以容纳窗口的按钮。在该框架内,创建两个按钮。第一个按钮的标签为 OK ,并在用户单击时执行子例程 color_sub。第二个按钮的标签为 Exit,并在单击时退出程序。例如:my $button_frame = $mw->Frame()->pack(-side => "bottom");
my $button_color = $button_frame->Button(-text => "OK",
                     -command => &color_sub)->pack(-side => "left");
my $button_exit = $button_frame->Button(-text => "Exit",
                    -command => sub{exit})->pack(-side => "right");

  下面的子例程显示一个消息框,通知用户他们选择的颜色。当用户单击 OK 时,该消息框将销毁。例如:sub color_sub {
 $mw->messageBox(-message => "You selected $color!", -type => "ok");
}

  Checkbutton

  checkbutton 小部件显示一个或多个复选框。用户可以选择其中一个或多个复选框。下面的示例演示了 checkbutton 小部件的使用:#!/usr/bin/perl -w
use Tk;
use strict;
my $mw = MainWindow->new;
$mw->geometry("300x150");
$mw->title("Check Button Test");
my $check1 = 'NOT CHECKED';
my $check2 = 'NOT CHECKED';
my $check3 = 'NOT CHECKED';
my $check_frame = $mw->Frame()->pack(-side => "top");
$check_frame->Label(-text=>"Select some check buttons.")->pack(-side => "top")->pack();
my $chk1 = $check_frame->Checkbutton(-text => 'Check #1',
                   -variable => $check1,
                   -onvalue => 'CHECKED',
                   -offvalue => 'NOT CHECKED')->pack();
my $chk2 = $check_frame->Checkbutton(-text => 'Check #2',
                   -variable => $check2,
                   -onvalue => 'CHECKED',
                   -offvalue => 'NOT CHECKED')->pack();
my $chk3 = $check_frame->Checkbutton(-text => 'Check #3',
                   -variable => $check3,
                   -onvalue => 'CHECKED',
                   -offvalue => 'NOT CHECKED')->pack();
my $button_frame = $mw->Frame()->pack(-side => "bottom");
my $ok_button = $button_frame->Button(-text => 'OK',
                    -command => &check_sub)->pack(-side => "left");
my $exit_button = $button_frame->Button(-text => 'Exit',
                    -command => sub{exit})->pack(-side => "right");
sub check_sub {
 my $check_msg = "Check #1: $check1nCheck #2: $check2nCheck #3: $check3";
 $mw->messageBox(-message => "Check Button Summary:n$check_msg", -type => "ok");
}
MainLoop;

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

  图 5. checkbutton 小部件示例

了解 Perl/Tk 模块,第 2 部分: 中级小部件

  首先,为 checkbutton 定义三个变量,并设置为缺省值“NOT CHECKED”。例如:my $check1 = 'NOT CHECKED';
my $check2 = 'NOT CHECKED';
my $check3 = 'NOT CHECKED';

  下一步,创建一个框架来组织 label 小部件和 checkbutton 小部件。同时创建标签并对其进行包装,使其与框架顶部对齐。例如:my $check_frame = $mw->Frame()->pack(-side => "top");
$check_frame->Label(-text=>"Select some check buttons.")->pack(-side => "top")->pack();

  创建三个 checkbutton,标签分别为 Check #1、Check #2 和 Check #3。向它们分配预定义变量 $check1 至 $check3,并设置 onvalue 和 offvalue 属性以向用户显示适当的文本。例如:my $chk1 = $check_frame->Checkbutton(-text => 'Check #1',
                   -variable => $check1,
                   -onvalue => 'CHECKED',
                   -offvalue => 'NOT CHECKED')->pack();
my $chk2 = $check_frame->Checkbutton(-text => 'Check #2',
                   -variable => $check2,
                   -onvalue => 'CHECKED',
                   -offvalue => 'NOT CHECKED')->pack();
my $chk3 = $check_frame->Checkbutton(-text => 'Check #3',
                   -variable => $check3,
                   -onvalue => 'CHECKED',
                   -offvalue => 'NOT CHECKED')->pack();

  创建第二个框架来组织按钮。在该框架中创建两个按钮。第一个按钮的标签为 OK,用于触发子例程 check_sub。第二个按钮执行该子例程以退出 Perl 脚本。例如:my $button_frame = $mw->Frame()->pack(-side => "bottom");
my $ok_button = $button_frame->Button(-text => 'OK',
                    -command => &check_sub)->pack(-side => "left");
my $exit_button = $button_frame->Button(-text => 'Exit',
                    -command => sub{exit})->pack(-side => "right");

  子例程 check_sub 定义了一个名为 $check_msg 的变量,其值为每个 checkbutton 的状态,并使用 messageBox 小部件显示到变量 $check_msg 的输出。例如:sub check_sub {
 my $check_msg = "Check #1: $check1nCheck #2: $check2nCheck #3: $check3";
 $mw->messageBox(-message => "Check Button Summary:n$check_msg", -type => "ok");
}

  Menu 和 menubutton

  menu 小部件是一种在单个整洁的列中显示项的简便方法。大多数复杂的 GUI 应用程序都包含某种形式的菜单,其中可能仅包含一个退出功能或包含 20 个选项。下面的脚本演示了创建菜单有多么容易:#!/usr/bin/perl -w
use Tk;
use strict;
my $mw = MainWindow->new;
$mw->geometry("300x150");
$mw->title("Menu Test");
my $main_menu = $mw->Menu();
$mw->configure(-menu => $main_menu);
my $file_menu = $main_menu->cascade(-label=>"File", -underline => 0, -tearoff=>0);
$file_menu->command(-label=>"Exit", -underline=>0, -command=>sub{exit});
$main_menu->command(-label=>"Say Hello", -underline => 0,
          -command=>sub{$mw->messageBox(-message=>"Hello!", -type => "ok")});
MainLoop;

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

  图 6. menu 小部件示例

了解 Perl/Tk 模块,第 2 部分: 中级小部件

  创建 menu 小部件,并开始配置它,从而为菜单项做准备。例如:my $main_menu = $mw->Menu();
$mw->configure(-menu => $main_menu);

  现在创建 File 菜单。例如:my $file_menu = $main_menu->cascade(-label=>"File", -underline => 0, -tearoff=>0);

  使用一个退出脚本的子例程,在 File 菜单下创建一个 Exit 命令。例如:$file_menu->command(-label=>"Exit", -underline=>0, -command=>sub{exit});

  创建另一个菜单,并将其标签设置为 Say Hello。例如:$main_menu->command(-label=>"Say Hello", -underline => 0,
          -command=>sub{$mw->messageBox(-message=>"Hello!", -type => "ok")});

  与将命令包括在此菜单之下不同,可以在此菜单本身之上配置一个命令。当您选择此菜单时,将会出现一个显示“Hello!”的消息框。menubutton 小部件与 menu 小部件类似,只不过它包括一种显示与菜单关联的文本或图像的方式。下面的示例描述如何将 menubutton 小部件添加到应用程序中,以及如何为命令添加一点颜色。#!/usr/bin/perl -w
use Tk;
use strict;
my $mw = MainWindow->new;
$mw->geometry("300x150");
$mw->title("Menubutton Test");
my $main_menu = $mw->Menu();
$mw->configure(-menu => $main_menu);
my $btn = $main_menu->Menubutton(-text => "Colorful Buttons...",
                 -underline => 0, -tearoff=>0);
$btn->command(-label => "Button #1",
       -activebackground => "blue",
       -foreground => "blue",
       -command => sub{$mw->messageBox(-message => "Button #1 Pressed")});
$btn->command(-label => "Button #2",
       -activebackground => "red",
       -activeforeground => "black",
       -background => "yellow",
       -foreground => "green",
       -command => sub{$mw->messageBox(-message => "Button #2 Pressed")});
$btn->command(-label => "Exit", -command => sub{exit});
MainLoop;