perl图形界面2

来源:互联网 发布:股票书籍推荐 知乎 编辑:程序博客网 时间:2024/05/16 14:51

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

引言

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. 一次打开多个窗口的示例
一次打开多个窗口的示例

本文回顾了一遍第一部分中的代码,以便复习本系列的第 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 useruse 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. 单独打开多个窗口的示例
单独打开多个窗口的示例

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

图 3. 打开的子窗口
打开的子窗口

首先,创建一个标签为 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 buttonsuse 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 小部件示例
radiobutton 小部件示例

您将首先定义变量 $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 -wuse 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: $check1\nCheck #2: $check2\nCheck #3: $check3";  $mw->messageBox(-message => "Check Button Summary:\n$check_msg", -type => "ok");}MainLoop;

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

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

首先,为 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 #1Check #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: $check1\nCheck #2: $check2\nCheck #3: $check3";  $mw->messageBox(-message => "Check Button Summary:\n$check_msg", -type => "ok");}

Menu 和 menubutton

menu 小部件是一种在单个整洁的列中显示项的简便方法。大多数复杂的 GUI 应用程序都包含某种形式的菜单,其中可能仅包含一个退出功能或包含 20 个选项。下面的脚本演示了创建菜单有多么容易:

#!/usr/bin/perl -wuse 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 小部件示例
menu 小部件示例

创建 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 -wuse 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;

运行此脚本将生成如图 7、8 和 9 所示的 GUI 应用程序。

图 7. menubutton 小部件示例
menubutton 小部件示例
图 8. Menubutton 小部件示例:将鼠标移动到 Button #1 上
Menubutton 小部件示例:将鼠标移动到 Button #1 上
图 9. Menubutton 小部件示例:将鼠标移动到 Button #2 上
Menubutton 小部件示例:将鼠标移动到 Button #2 上

首先,创建 menubutton 小部件,并准备向其添加命令。例如:

my $btn = $main_menu->Menubutton(-text => "Colorful Buttons...",                                 -underline => 0, -tearoff=>0);

现在在 $btn menubutton 上创建三个命令。例如:

$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});

第一个命令具有蓝色背景:当该命令未突出显示时,背景保持缺省的灰色,文本为蓝色。该命令还具有活动蓝色背景:当突出显示该命令时,其背景变为蓝色,而文本则保持为缺省的灰色。当激活 menubutton 时,将出现一个消息框并声明已单击了该按钮。第二个按钮在被选择时执行类似的操作。但是,其活动背景为红色,活动前景为黑色,背景为黄色,前景为绿色。第三个命令退出脚本。

Scrollbar

scrollbar 小部件控制其他小部件的视图,例如 text 和 entry 小部件。添加此小部件使得用户可以使用滚动条上下移动目标小部件。将 scrollbar 小部件添加到应用程序是非常方便快捷的。例如:

#!/usr/bin/perl -wuse Tk;use strict;my $mw = MainWindow->new;$mw->geometry("200x100");$mw->title("Scrollbar Test");my $scroll_text = $mw->Scrollbar();my $main_text = $mw->Text(-yscrollcommand => ['set', $scroll_text],                          -background => 'black',                          -foreground => 'red');$scroll_text->configure(-command => ['yview', $main_text]);$scroll_text->pack(-side=>"right", -expand => "no", -fill => "y");$main_text->pack(-side => "left", -anchor => "w",                 -expand => "yes", -fill => "both");MainLoop;

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

图 10. Scrollbar 小部件示例
Scrollbar 小部件示例

首先创建 scrollbar 小部件。例如:

my $scroll_text = $mw->Scrollbar();

创建一个非缺省颜色的 text 小部件,并作为应用程序 y(垂直)轴上的 scrollcommand 绑定 scrollbar 小部件 ($scroll_text)。例如:

my $main_text = $mw->Text(-yscrollcommand => ['set', $scroll_text],                          -background => 'black',                          -foreground => 'red');

允许用户通过移动滚动条来控制目标小部件的移动,从而与 scrollbar 小部件交互。例如:

$scroll_text->configure(-command => ['yview', $main_text]);

包装 text 以及 scrollbar 小部件,并很好地将它们对齐。例如:

$scroll_text->pack(-side=>"right", -expand => "no", -fill => "y");$main_text->pack(-side => "left", -anchor => "w",                 -expand => "yes", -fill => "both");

实际运用

现在您已经在一个脚本中集合了几个中级小部件。例如:

#!/usr/bin/perl -wuse Tk;use strict;my $ver = "1.0.0";my $mw = MainWindow->new;$mw->geometry("500x150");$mw->title("All-In-One Demo #2");my $main_menu = $mw->Menu();$mw->configure(-menu => $main_menu);# give the user a way to exit the scriptmy $file_menu = $main_menu->cascade(-label=>"File", -underline => 0, -tearoff=>0);$file_menu->command(-label=>"Exit", -underline=>0, -command => sub{exit});# everyone needs a little helpmy $help_menu = $main_menu->cascade(-label => "Help", -underline => 0, -tearoff => 0);$help_menu->command(-label => "Version", -underline => 0,                    -command => sub{$mw->messageBox(-message => "Version: $ver",                                                    -type => "ok")});$help_menu->command(-label => "About Program", -underline => 0, -command => \&show_about);my $greeting_frame = $mw->Frame()->pack(-side => "top");$greeting_frame->Label(-text => "Tell me a little about yourself...")->pack();my $info_frame = $mw->Frame()->pack(-side => "top");my $last_name = $info_frame->Entry()->pack(-side => "right");$info_frame->Label(-text => "Last Name")->pack(-side => "right");my $stat = "Mr";$info_frame->Radiobutton(-text => "Mr", -value => "Mr",                         -variable => \$stat)->pack(-side => "right");$info_frame->Radiobutton(-text => "Mrs", -value => "Mrs",                         -variable => \$stat)->pack(-side => "right");$info_frame->Radiobutton(-text => "Miss", -value => "Miss",                         -variable => \$stat)->pack(-side => "right");my $pet_info_frame = $mw->Frame()->pack(-side => "top");$pet_info_frame->Label(-text => "Check all pets you like?")->pack(-side => "left");my $chk1 = "no";my $chk2 = "no";my $chk3 = "no";my $chk4 = "no";my $chk5 = "no";my $pet1_chk = $pet_info_frame->Checkbutton(-text => "Cat",                                            -variable => \$chk1,                                            -onvalue => "yes",                                            -offvalue => "no")->pack(-side => "right");my $pet2_chk = $pet_info_frame->Checkbutton(-text => "Dog",                                            -variable => \$chk2,                                            -onvalue => "yes",                                            -offvalue => "no")->pack(-side => "right");my $pet3_chk = $pet_info_frame->Checkbutton(-text => "Fish",                                            -variable => \$chk3,                                            -onvalue => "yes",                                            -offvalue => "no")->pack(-side => "right");my $pet4_chk = $pet_info_frame->Checkbutton(-text => "Snake",                                            -variable => \$chk4,                                            -onvalue => "yes",                                            -offvalue => "no")->pack(-side => "right");my $pet5_chk = $pet_info_frame->Checkbutton(-text => "Hamster",                                            -variable => \$chk5,                                            -onvalue => "yes",                                            -offvalue => "no")->pack(-side => "right");my $button_frame = $mw->Frame()->pack(-side => "top");$button_frame->Button(-text => "Ok", -command => \&update_output)->pack();my $output_frame = $mw->Frame()->pack(-side => "bottom");my $output_scroll = $output_frame->Scrollbar();my $output_text = $output_frame->Text(-yscrollcommand => ['set', $output_scroll]);$output_scroll->configure(-command => ['yview', $output_text]);$output_scroll->pack(-side => "right", -expand => "no", -fill => "y");$output_text->pack();sub update_output {  my $lname = $last_name->get();  if ($lname eq "") { $lname = "No Name"; }  my $output = "Hello $stat. $lname!\nI like the following too!";  if ( $chk1 eq "yes" ) { $output = "$output\nCats"; }  if ( $chk2 eq "yes" ) { $output = "$output\nDogs"; }  if ( $chk3 eq "yes" ) { $output = "$output\nFish"; }  if ( $chk4 eq "yes" ) { $output = "$output\nSnakes"; }  if ( $chk5 eq "yes" ) { $output = "$output\nHamsters"; }  $output_text->delete('0.0', 'end');  $output_text->insert("end", $output);}sub show_about {  my $help_win = $mw->Toplevel;  $help_win->geometry("300x50");  $help_win->title("About Program");  my $help_msg = "This help page is an example of using multiple windows.";  $help_win->Label(-text => $help_msg)->pack();  $help_win->Button(-text => "Ok", -command => [$help_win => 'destroy'])->pack();}MainLoop;

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

图 11. 单个示例中的所有上述小部件
单个示例中的所有上述小部件

0 0
原创粉丝点击