首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

在 Perl/Tk 中使用高级窗口小部件--简化的数据入口:Tk::DateEntry 和 Tk::PathEntry

在 Perl/Tk 中使用高级窗口小部件--简化的数据入口:Tk::DateEntry 和 Tk::PathEntry

通过显示合法的输入并允许用户自其中进行选择,         Tk:ateEntry 和         Tk:athEntry 窗口小部件简化了结构化数据的输入(分别是日期和文件路径)。      
DateEntry 窗口小部件上有一个文本输入域以及一个紧挨着的按钮。点击那个按钮,会在下拉菜单中显示一个日历,然后使用鼠标选择日期,相应的字符串就会输入到本文输入域中。      
图 3. DateEntry 窗口小部件 展示了与此例相关的代码。选用         Convert 来计算从 Unix 诞生到现在的秒数,并将它们显示在本文输入域上面的         Label 窗口小部件中。      
清单 3: 使用 DateEntry 窗口小部件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
use Tk;
use Tk:ateEntry;
use Time:ocal;
%idx_for_mon = ( JAN=>1, FEB=>2, MAR=>3, APR=> 4, MAY=> 5, JUN=> 6,
         JUL=>7, AUG=>8, SEP=>9, OCT=>10, NOV=>11, DEC=>12 );
$input = '01-APR-2004'; # Initial value for display
$mw = MainWindow->new();
$mw->geometry( '200x80' );
$mw->resizable( 0, 0 );
$label = $mw->Label( -text=>'' )->pack;
$entry = $mw->DateEntry( -textvariable=>\$input, -width=>11,
             -parsecmd=>\&parse, -formatcmd=>\&format )->pack;
$mw->Button( -text=>'Quit', -command=>sub{ exit } )->pack( -side=>'right' );
$mw->Button( -text=>'Convert',
         -command=>sub{ convert( $input, $label ) } )->pack( -side=>'left' );
MainLoop;
# called on dropdown with content of \$textvariable, must return ( $yr, $mon, $day )
sub parse {
  my ( $day, $mon, $yr ) = split '-', $_[0];
  return ( $yr, $idx_for_mon{$mon}, $day );
}
# called on user selection with ($yr, $mon, $day), must return formatted string
sub format {
  my ( $yr, $mon, $day ) = @_;
  my %mon_for_idx = reverse %idx_for_mon;
  return sprintf( "%02d-%s-%2d", $day, $mon_for_idx{ $mon }, $yr );
}
# perform the conversion to epoch seconds when the corresponding button is pressed
sub convert {
  my ( $input, $label ) = @_;
  my ( $yr, $mon, $day ) = parse( $input );
  my $output = "Epoch seconds: " . timelocal( 0, 0, 0, $day, $mon-1, $yr-1900 );
  $label->configure( -text => $output );
}




由于以字符串形式来描述同一日期的方式很多,所以日期的输入是困难的。        DateEntry 提供了三种标准的日期格式(MM/DD/YYYY、YYYY/MM/DD 和 DD/MM/YYYY),可以通过         -dateformat 选项来选择使用它们。如果希望使用不同的日期格式,那么程序员就不得不使用         -parsecmd 和         -formatcmd 回调来显式地给出转换例程。在上面的例子中,我们使用了一个定制的日期格式,以三个字母的缩写的形式表示月份。当将输入的字符串解析为数字时,我们使用的是哈希表(hash)         %idx_for_mon,它保持了每个月份(1..12)给定缩写的数字索引。当用户从下拉菜单中选择了一个日期后,它必须被格式化为相应的字符串,需要进行反向查找,也就是根据索引查找缩写。我们在         format 中使用         reverse 命令动态地构建了这样一个数据结构。由于这个命令需要以一个数组作为参数,所以将原来的哈希表拆解为一个数组,拆解的方式是,在数组中,每个值跟在它的键的后面。然后这个数组被翻转(所以现在先前的键跟在值的后面)并重新转换为一个哈希表。这个技巧在这里是可以成功的,因为键和值都唯一(此外,要获得关于此内容的更多资料,请参考在  中列出的        Learning Perl)。      
convert 以包含有输入字符串的变量以及对         Label 窗口小部件的引用作为参数,以改变         Label 所显示的值。在这里,我们没有将对回调的引用和匿名数组中的参数值传递给         -command 属性;取而代之的是,我们在一个匿名子例程中直接去调用回调函数(一个         closure)。原因与变量的范围有关;参阅 中的完整说明。      
最后,         Tk:athEntry 窗口小部件是非常简单的:它具有一个输入路径名的文本输入域—— 但是用到了一个技巧!它的方式类似于         tcsh 或 Emacs 的微缓存,按下         Tab 将尽可能完全地补充完整输入域的内容,而且,如果不能明确地补充完整当前的内容,则它将弹出一个列表框,列出所有可能的选择。奇怪的是,列表框的颜色不能被改变 —— 除非有人愿意去编辑底层Perl 模块的代码。      
图 4. PathEntry 窗口小部件清单 4: 使用 PathEntry 窗口小部件
1
2
3
4
5
6
7
8
9
10
11
use Tk;
use Tk:athEntry;
use Cwd;
$path = cwd();
$mw = MainWindow->new();
$mw->geometry( '300x80' );
$mw->resizable( 0, 0 );
$mw->athEntry( -textvariable=>\$path )->pack;
$mw->Label( -textvariable=>\$path, -foreground=>'blue' )->pack;
$mw->Button( -text=>'Quit', -command=>sub{ exit } )->pack;
MainLoop;




PathEntry 如此吸引人的原因是,它只是一个窗口小部件,而不是一个对话框。它可以(实际上是必须)在程序中与其他窗口小部件组合使用。因此,它提供了一个向应用程序添加文件选择能力的非常轻量级的方法。
返回列表