perl/tk_在Perl / Tk中使用高级小部件
perl/tk
与Perl语言的广泛使用相比,Perl的GUI工具集Perl / Tk不太受欢迎。 这很奇怪,因为它可以说是最容易编程的GUI工具包之一(至少对于UNIX平台而言),因此建议将其自身用于用户界面原型设计或快速为用户提供围绕隐含命令行工具的用户友好包装器。
对Perl / Tk相对漠不关心的一个原因似乎是人们认为它不是很强大,并且不适合复杂的应用程序。 但是,许多提供更复杂功能的小部件都可以作为用户在CPAN上的贡献。 在本文中,我将介绍其中的一些内容,并展示如何使用它们来创建更丰富的用户体验。 我还将指出一些用于Perl / Tk编程的更普遍有用的技术。
(当然,Perl / Tk的另一个问题是它的小部件看起来很丑陋,并且不具有“主题化”。不幸的是,我对此无能为力。)
先决条件和可用性
整个过程都假定您具有Perl的丰富知识以及至少具有Perl / Tk的基本经验以及一般的GUI编程概念(事件,小部件,回调,几何管理器)。 您可以在本文的“ 相关主题”部分中找到有关Perl / Tk的入门资源。
您可以从CPAN(综合Perl存档网络)免费下载本文讨论的所有小部件。 大多数选项的选项超出了此处所能解释的范围:每个小部件的perldoc以及(在某些情况下)源代码提供了最终的完整参考。
分页框架:Tk :: NoteBook
Tab是一个常见的GUI小部件,它有助于将大量选项组合为较小的子集,从而为例如复杂的对话框添加结构。
Tk::NoteBook
具有Tab外观和Perl / Tk语义的小部件是Tk::NoteBook
。 使用三个选项卡的示例如图1所示。 请注意第三个选项卡被禁用。
图1. NoteBook小部件
此示例由以下代码产生:
清单1:使用NoteBook小部件
use Tk;
use Tk::NoteBook;$mw = MainWindow->new();
$mw->geometry( "400x100" );
$book = $mw->NoteBook()->pack( -fill=>'both', -expand=>1 );$tab1 = $book->add( "Sheet 1", -label=>"Start", -createcmd=>\&getStartTime );
$tab2 = $book->add( "Sheet 2", -label=>"Continue", -raisecmd=>\&getCurrentTime );
$tab3 = $book->add( "Sheet 3", -label=>"End", -state=>'disabled' );$tab1->Label( -textvariable=>\$starttime )->pack( expand=>1 );
$tab2->Label( -textvariable=>\$raisetime )->pack( expand=>1 );
$tab3->Button( -text=>'Quit', -command=>sub{ exit; } )->pack( expand=>1 );MainLoop;sub getStartTime {$starttime = "Started at " . localtime;
}sub getCurrentTime {$raisetime = " Last raised at " . localtime;$book->pageconfigure( "Sheet 3", -state=>'normal' );
}
指定回调参数
我们遇到了两种不同的方法来为回调指定参数-要么作为一个平面列表:
-command=>[ \&fct, $slide, $bar1, $bar2 ]
或作为匿名子例程中回调的直接调用:
-command=>sub{ convert( $input, $label ) }
两种方法之间的差异与可变范围有关。 更准确地说,是在准确的时间评估参数。
在第一种情况下,在执行包含-command
属性的构造函数时会评估参数。 如果参数的值稍后更改,则在回调内部将不可见。 在ProgressBar
示例中这很好,因为参数是对应用程序中小部件的引用,这些小部件一旦构建,就不再受更改。
相反,在第二种情况下使用的匿名子例程的内容在实际调用该子例程之前不会进行评估。 换句话说,回调在执行回调时会看到参数的值。 这在DateEntry
示例中很重要,因为$input
变量包含最新的用户输入,因此在整个程序中经常更改。
最后,由于convert
函数的主体太大,无法方便地放入inline sub{ }
声明中,因此我们将convert
保留为单独的函数,仅从匿名子例程内部调用它。
像在任何Perl / Tk应用程序中一样,我们首先指定要使用的模块,然后创建MainWindow
。 请注意, Tk::NoteBook
以及CPAN上的其他贡献的小部件都不是标准Tk分发的一部分,因此需要明确指定。
我们创建一个NoteBook
小部件作为MainWindow
子级,然后添加三个选项卡。 add()
函数的第一个参数是符号名称,通过它可以在笔记本中引用生成的页面:我们将在下面使用它。
使用NoteBook
小部件时,我应该对几何管理进行两个评论。 首先,尽管选项卡本身就是窗口小部件,但是不需要pack
它们。 它们的几何形状管理由NoteBook
处理。 其次,如果NoteBook
小部件的父窗口是可调整大小的,则在pack
NoteBook
时同时指定-fill
和-expand
属性非常重要。 后者将确保NoteBook
的分配矩形将始终扩展以填充可用空间,而前者将确保实际的NoteBook
小部件将扩展以填充其分配矩形。
选项卡接受各种属性。 在这里,我们演示-createcmd
, -raisecmd
和-state
。 前两个可用于注册回调,分别在首次创建选项卡和引发选项卡时分别调用它们; 而最后一个可以接受normal
和disabled
的值。 我们还使用了第二个选项卡上的-raisecmd
回调,以便在第一次提升第二个选项卡后将其从禁用状态切换到活动状态。 我们使用封闭的NoteBook
小部件上的pageconfigure()
函数,将引用的选项卡的符号名称作为第一个参数传递。
多功能图形显示:Tk :: ProgressBar
Tk::ProgressBar
是一个小部件,可显示标量值的图形表示。 进度条通常用于在下载大文件或执行类似的长期运行任务时向用户提供反馈。 Perl / Tk中的相应小部件提供了一些特殊功能,这些功能也可能使其对其他用途具有吸引力。
图2. ProgressBar小部件
此示例包含两个ProgressBar
小部件,它们与标准Scale
耦合。 移动滑块可通过调用名为fct
的回调来更改显示的颜色条的长度,该回调将调用ProgressBar
上的value
函数以设置新的长度。 值100
对应于可见色条的全长。 可以分别使用-to
和-from
属性来更改此值,也可以更改与零长度颜色条对应的值。
清单2展示了一些可以自定义颜色条外观的方式。 底部的ProgressBar
分为十个块,每个块之间相隔一像素的间隙。 这些是默认值。 可以通过显式指定blocks
和gap
属性的值来设置它们。 一些试验-padx
, -pady
, -length
和-borderwidth
属性一般要求。
-colors
属性接受对包含位置和颜色对的数组的引用。 (请注意,位置必须按升序排序!)最后一个指定的颜色将用于颜色栏,直到到达下一个位置为止,此时颜色将更改。 因此,定义@colors = ( 0, "red", 50, "green" );
产生一个在左侧为红色,在另一侧为绿色的颜色条。 在这里,我提供了100个不同的值,跨越了顶部ProgressBar
的彩虹色。 请注意,调整窗口大小时,顶部的ProgressBar
更改其长度。
清单2:使用ProgressBar
小部件
use Tk;
use Tk::ProgressBar;@colors = ( 0, '#ff002a', 1, '#ff0014', 2, '#ff000a', 3, '#ff0500', 4, '#ff1000',5, '#ff1b00', 6, '#ff3000', 7, '#ff3b00', 8, '#ff4600', 9, '#ff5100',10, '#ff6100', 11, '#ff7600', 12, '#ff8100', 13, '#ff8c00', 14, '#ff9700',15, '#ffa100', 16, '#ffbc00', 17, '#ffc700', 18, '#ffd200', 19, '#ffdd00',20, '#ffe700', 21, '#fffd00', 22, '#f0ff00', 23, '#e5ff00', 24, '#dbff00',25, '#d0ff00', 26, '#baff00', 27, '#afff00', 28, '#9fff00', 29, '#95ff00',30, '#8aff00', 31, '#74ff00', 32, '#6aff00', 33, '#5fff00', 34, '#54ff00',35, '#44ff00', 36, '#2eff00', 37, '#24ff00', 38, '#19ff00', 39, '#0eff00',40, '#03ff00', 41, '#00ff17', 42, '#00ff21', 43, '#00ff2c', 44, '#00ff37',45, '#00ff42', 46, '#00ff57', 47, '#00ff67', 48, '#00ff72', 49, '#00ff7d',50, '#00ff87', 51, '#00ff9d', 52, '#00ffa8', 53, '#00ffb8', 54, '#00ffc3',55, '#00ffcd', 56, '#00ffe3', 57, '#00ffee', 58, '#00fff8', 59, '#00faff',60, '#00eaff', 61, '#00d4ff', 62, '#00c9ff', 63, '#00bfff', 64, '#00b4ff',65, '#00a9ff', 66, '#008eff', 67, '#0083ff', 68, '#0079ff', 69, '#006eff',70, '#0063ff', 71, '#004eff', 72, '#003eff', 73, '#0033ff', 74, '#0028ff',75, '#001dff', 76, '#0008ff', 77, '#0200ff', 78, '#1200ff', 79, '#1d00ff',80, '#2800ff', 81, '#3d00ff', 82, '#4800ff', 83, '#5300ff', 84, '#5d00ff',85, '#6e00ff', 86, '#8300ff', 87, '#8e00ff', 88, '#9900ff', 89, '#a300ff',90, '#ae00ff', 91, '#c900ff', 92, '#d400ff', 93, '#df00ff', 94, '#e900ff',95, '#f400ff', 96, '#ff00f3', 97, '#ff00e3', 98, '#ff00d9', 99, '#ff00ce' );$mw = MainWindow->new();
$mw->geometry( '250x150' );
$mw->resizable( 1, 0 );$bar1 = $mw->ProgressBar( -borderwidth=>2, -blocks=>100, -gap=>0,-troughcolor=>'white',-colors=>\@colors,-length=>106 )->pack( -padx=>5, -pady=>5, -fill=>'x' );$slide = $mw->Scale( -orient=>'horizontal', -length=>150,-showvalue=>0, -tickinterval=>20 )->pack;$bar2 = $mw->ProgressBar( -padx=>2, -pady=>2, -borderwidth=>2,-troughcolor=>'#BFEFFF', -colors=>[ 0, '#104E8B' ],-length=>106 )->pack;$mw->Button( -text=>'Quit', -command=>sub{ exit } )->pack( -padx=>15, -pady=>15,-anchor=>'se' );$slide->configure( -command=>[ \&fct, $slide, $bar1, $bar2 ] );MainLoop;sub fct {my ( $slide, $bar1, $bar2 ) = @_;my $val = $slide->get();$bar1->value( 100 - $val );$bar2->value( $val );
}
我们不在Scale
小部件的configure
函数中指定Scale
小部件的回调,而是在以后使用configure
函数指定它。 原因是我们需要同时引用两个ProgressBar
作为回调的参数,并且在调用Scale
构造函数时,尚未全部定义它们。 更改小部件构造函数的调用顺序是不可能的,因为这将更改小部件的打包顺序。
此代码还演示了一种指定回调参数的方法:作为匿名列表,其中对回调的引用作为第一个元素被调用,后跟必需的参数。 如果回调不需要参数,则不需要创建匿名列表,因为Perl将在列表上下文中评估的标量值视为单元素数组。 (有关在Perl列表的详细信息,请参见学习Perl中,第二版 ,在上市的相关信息 )。我们会遇到不同的方法来发送参数如下回调; 查看补充工具栏以讨论两种方法之间的区别。
为颜色条的任何部分选择任意颜色的自由使得ProgressBar
可以用作一般的显示小部件,例如:颜色可以用于指示显示的变量是否在“正常”参数范围内。 不幸的是,该小部件不支持-orient
属性。 ProgressBar
始终水平放置。
简化的数据输入:Tk :: DateEntry和Tk :: PathEntry
Tk::DateEntry
和Tk::PathEntry
小部件通过提供有效输入的显示并允许用户从中选择来简化结构化数据的输入(分别为日期和文件路径)。
DateEntry
小部件显示带有相邻按钮的文本输入字段。 单击该按钮将在下拉菜单中显示日历,然后使用鼠标选择日期将相应的字符串输入到文本输入字段中。
图3. DateEntry小部件
清单3显示了与此示例相关的代码。 选择“ Convert
计算自Unix时代开始以来的秒数,并将其显示在文本输入字段上方的“ Label
小部件中。
清单3:使用DateEntry小部件
use Tk;
use Tk::DateEntry;use Time::Local;%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
回调显式提供转换例程。 在上面的示例中,我们使用自定义日期格式,使用3个字母的首字母缩写词显示月份。 在将输入字符串解析为其数字组成部分时,我们使用哈希%idx_for_mon
,该哈希%idx_for_mon
保留每个月的数字索引(1..12)(以其缩写为准)。 当用户从下拉菜单中选择日期时,必须将其格式化为相应的字符串,需要相反的查找,即给定索引的首字母缩写。 我们使用reverse
命令在format
例程中动态建立了这样的数据结构。 由于此命令需要一个数组,因此将原始哈希散列到数组中,以使值遵循数组中各自的键。 然后将此数组反转(以便现在以前的键跟随其值)并转换回哈希。 这招在这里工作,因为这两个键和值是唯一的(再次,它的更多信息,请参见学习Perl,它是在列出的相关主题 )。
convert
函数将包含输入字符串的变量以及对Label
小部件的引用作为参数,以便它可以更改Label
所示的值。 这里,我们没有将对回调的引用以及匿名数组中的参数值传递给-command
属性; 取而代之的是,我们从匿名子例程( 闭包 )中直接调用回调函数。 原因与可变范围有关。 请参阅补充工具栏以获取完整说明。
最后, Tk::PathEntry
小部件非常简单:它为路径名提供了一个文本输入字段-但要Tk::PathEntry
! 与tcsh
或Emacs迷你缓冲区的行为类似,按Tab
键将尽可能完成输入字段的内容,如果无法明确完成当前内容,则会弹出一个可能选择的列表框。 奇怪的是,列表框的颜色无法更改-除非您想编辑基础Perl模块的代码。
图4. PathEntry小部件
清单4:使用PathEntry小部件
use Tk;
use Tk::PathEntry;use Cwd;$path = cwd();$mw = MainWindow->new();
$mw->geometry( '300x80' );
$mw->resizable( 0, 0 );$mw->PathEntry( -textvariable=>\$path )->pack;
$mw->Label( -textvariable=>\$path, -foreground=>'blue' )->pack;
$mw->Button( -text=>'Quit', -command=>sub{ exit } )->pack;MainLoop;
使PathEntry
如此有趣的原因在于它只是一个小部件,而不是一个对话框。 它可以(实际上,必须)与程序中的其他小部件组合。 因此,它提供了一种非常轻巧的方式来向应用程序添加文件选择功能。
结论
这些只是Perl / Tk GUI工具包的一些“高级”小部件,允许开发人员使用Perl创建更丰富,更强大的用户界面。 此处讨论的所有小部件都可以作为CPAN的用户贡献免费提供。
翻译自: https://www.ibm.com/developerworks/opensource/library/l-ptkwidg/index.html
perl/tk
perl/tk_在Perl / Tk中使用高级小部件相关推荐
- python entry如何清空_Python tkinter,从类中清除Entry小部件
这是我正在调用的类,并且是来自其他文件的函数 class CalcFunc: def clearScreen(self): self.log("CLEAR (CE)") ent.d ...
- python entry如何清空_如何清除tkinter中来自Entry小部件的以前输入?
当我在Entry小部件中输入输入值a并点击Click Me.该按钮调用takes_input()方法,该方法更新Text小部件.看起来是这样的:如何清除tkinter中来自Entry小部件的以前输入? ...
- wordpress创建_十分钟即可在WordPress中创建动态小部件
wordpress创建 Have you tried to find functionality for a specific purpose in WordPress but failed to f ...
- python为text添加滚动条_在Tkinter中向一组小部件添加滚动条
概述 您只能将滚动条与一些小部件关联起来,根小部件和Frame不是那组小部件的一部分. 最常见的解决方案是创建一个画布小部件,并将滚动条与该小部件关联起来.然后,将包含标签小部件的框架嵌入到画布中.确 ...
- python中填充颜色结束的程序_在ttk/python中更改标签小部件的填充颜色
我试图用python中的ttk/tkinter显示图像.图像有一个白色的边框,我想在一个更大的白色背景上显示这个图像,所以它周围有很多空白.在 为此,我在标签中使用"padx"和& ...
- c语言context窗口,如何在gtk3中为窗口小部件设置特定的css类? (C)
我正在尝试gtk3中的CSS,我不明白如何使用特定的类. C代码: provider = gtk_css_provider_new(); display = gdk_display_get_defau ...
- python中label前景色的动态改变_在ttk / python中更改Label小部件的填充颜色
我试图在python中使用ttk / tkinter显示图像.图像有一个白色边框,我想在更大的白色背景上显示这个图像 – 所以它周围有很多白色空间. 为此,我在标签中使用"padx" ...
- android studio on/off 切换开关,如何使用android studio中的开关小部件来启用/禁用函数()?...
试试这个: import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JF ...
- qlistview 自定义控件_是否可以在QListView中添加自定义窗口小部件?
I have a large log data (100, 1000, 100000, ... records) and I want to visualize it in the following ...
最新文章
- Facebook Messenger要点燃聊天机器人革命,据说四月就发布!
- 【Leetcode | easy】反转整数
- else if mybatis 嵌套_新手如何书写C++代码,远离深度嵌套的if-else
- p2000专业软件测试对比,对比说说丽台p2000和p2200对比哪个好些?有何区别呢?良心点评实际情况...
- Python爬虫解析网页的4种方式 值得收藏
- 在html中使用javascript注意事项
- Sentinel降级简介_分布式系统集群限流_线程数隔离_削峰填谷_流量控制_速率控制_服务熔断_服务降级---微服务升级_SpringCloud Alibaba工作笔记0038
- 从“救火”到“井然有序”
- WIFI篇(3.python破解wifi--pywifi的介绍)
- openv 在 ubuntu(linux)上的编码编译
- 等保二级与等保三级的四大区别分析-行云管家
- crt是什么意思 windows编程_软件工程师应该知道的关于Windows API、CRT和STL二三事...
- 用java程序实现记单词_GitHub - whypro/Hello-Word: 用 JAVA(J2SE) 实现的一个背单词程序,可自由选择词库。...
- vue3.0+vite跑项目遇到的问题
- html/css移动界面侧滑效果
- 利用python进行数据分析(第二版)_第十三章
- MongoDB热备方案
- 图像处理------简单综合实例(大米计数)
- html5在线客服源码 websocket c#实现, im 即时通讯 完整的源代码,在线聊天
- 黑莓9930/9900开启电信4g网络,电信卡+3g上网