TCL-TK编程实践
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第3部分 TK基础
23TK基本原理
23.1TK中的Hello,World!
我们的第一个Tk脚本非常简单。
它创建了一个按钮,当你点击它时,就向标准输出设备打印“Hello,World!”。
在按钮控件上方是一个由窗口管理器提供的标题栏,本例中在X视窗系统中是twm。
23.1.1例23-1 “Hello,World!”Tk程序
第一行标识了脚本的解释器:
如果此脚本象其它NUIX命令文件那样被调用,则这个特殊的行是必要的,第2节描述了如何设置脚本于不同的平台上。
在这个脚本中有两个TCL命令:一个用来创建按钮,一个用来使其在显示上可见。
bu tton命令创建一个按钮的实例:
按钮的名字是.hello。
按钮上的标签是Hello,与此按钮相关联的命令是:
pack命令将按钮映射到屏幕上。
并提供了一些堆叠参数,所以在按钮周围有空间。
当你将这两个命令键入wish中时,当button命令给出时,你不会看到任何东西。
然而,在pack命令之后,你将会看到空的主窗口将会收缩到足以容纳按钮和其添充空隙(padd ing)。
包装器的行为在第24和第25章进行深入的讨论。
Tk使用一种基本对象的系统来创建和命令控件。
与每一种小控件(如按钮)相关联的是一个用于创建此种类别控件实例的命令。
当小控件被创建时,一个作用在这个控件实例上的一个新的TCL命令就定义了。
例23-1创建了一个名为.hello的按钮,并且我们可以使用其名字作为一个TCL命令来操纵此按钮。
例如,我们可以使用此按钮高亮几次:
或者,我们可以运行与此按钮相关联的命令:
Tk有控件类和实例,但是它并不是完全面向对象的。
不可能去对一个控件类派生子类并继承。
相反,Tk,提供了非常灵活的控件,可以通过多种方式调节其外观。
资源数据库可以存储被许多控件共享的配置信息,并且新的类也可以被引入到组资源中。
控件行为通过使用分缓绑定的绑定标签得到共享。
Tk使用部件(composition)来组装共享行为和属性的控件。
23.2Tk小控件的命名
按钮实例名字.hello中的句点是必需的。
Tk使用了一种可以反映出控件所在层次的命名系统。
层次的根就是应用程序的主窗口,其名字就是一个简单的点(也就是.)。
这与U NIX系统中的目录命名习惯很相似,其跟目录名为/,/也用来分隔文件名的组成部分。
Tk
以同样的方式使用句点。
主窗口的每一个子窗口控件以象.foo这样来命名。
.foo的一个子控件将是.foo.bar,等等。
正如文件系统中目录可以作为其它文件和目录的容器一样,Tk窗口层次使用框架控件作为其它控件和框架的容器。
构成Tk路径的每一部分必须以小写字母或数字开头。
显然也不能包含句点。
小写字母是为了避免与以大写字母开头的资源类名冲突。
一个资源名可以包含Tk路径组成部分和T k控件类别,并使用大小写来区分它们。
第31章详细描述了资源。
用变量存储控件名。
Tk命名系统有一个缺点。
如果你的界面变化足够多以至导致某些控件改变了他们在控件层次中的位置。
在这种情况下,它们可能需要改变其名字。
你可以通过使用变量来保存重要控件的名字这种方式与这个程序麻烦相隔离。
使用一个变量的引用而不是控件的路径名以便你需要改变什么,或者你想不其它的界面是得用你的代码。
控件创建命令返回控件的名字:
你可以将$b当作命令来操作按钮:
23.3Tk小控件的配置
例23-1展示了Tk命令中普遍使用的一种命名参数的传递方式。
成对的参数指定了控件的属性。
属性名以-开始,如-text,下一个参数就是这个属性的值。
即使是简单的Tk 控件也可能有一打或更多的可以通过这种方式指定的属性,复杂控件可能有30或更多属性。
然而,Tk的魅力在于你仅需要指定默认值不太好的属性。
这个可以通过Hello,World例子的简易性得到证明。
最后,每一个控件实例都支持一个configure操作,可以简写为config,它可以查询和改变这些属性。
Config的语法,使用相同的创建控件时使用的命名参数对。
例如,我们可以改变这个按钮的背景与红色,即使它已经被创建并已经被映射到屏幕上:
控件属性可以在任何时候重新定义,即使是按钮在创建时的text和command。
下面的命令将.hello变成一个goodbye按钮:
控件有一个cget操作来查询某个属性的当前值:
你可以用不带参数的configure来得到关于一个控件属性的更多细节:
返回的信息包括命令行开关,资源名称,类名,默认值和当前值。
类名和资源名与31章中描述的资源机制有关。
如果你只指定configure不指定属性,则将返回控件所有属性配置信息的一个列表。
例23-2运用这个来打印出关于一个控件的所有信息:
23.3.1例23-2查看控件的所有属性
23.4Tk小控件的属性和资源数据库
一个控件属性以三种不同的方式命名:通过命令行选项,通过资源名、通过其资源类。
命令行选项就是TCL脚本中使用的形式。
此种形式都是小写字母并以连字符(例如,-off value)作前缀。
属性的资源名没有前导连字符,内部单词边界有大小字母(如,offVal ue)。
资源类以大写字母开头且内部单词边界有大写字母(如,OffValue)。
本书中的表格使用资源名列出控件的属性。
如果你想通过资源机制来指定控件的属性,你需要知道这些命名习惯。
命令行选项可以通过将资源名映射为全部小写字母衍生得到。
使用资源来指定属性的优点是,你不必更改代码中的属性值。
仅是通过少数资源数据库项,你就可以为你的所有控件指定属性。
另外,如果属性是通过资源指定的,用户可以提供交互式的资源值(或规格?)来由应用程序提供的值。
对于像颜色和字体的属性,对于用户来说是重要的。
资源规格在31章是详述。
23.4.1Tk手册页
本书提供了所有Tk命令的总结,控件的属性,默认绑定。
然而,为了绝对正确,你可能需要读随Tk的联机手册页。
它提供了Tk命令的完全参考。
你应该使用UNIX的man程序去读它们:
UNIX手册页中的tkman程序提供了非常友好的图形用户界面。
在Macintosh平台上,手册页格式化为HTML文档,可以在Tcl/Tk发行版本中的HTML Docs目录中找到。
在W indows中,手册格式化成帮助文档。
你可以在这个WEB上找到手册页:/man/
有许多属性对于大多数Tk控件是通用的。
这些属性在一个单独的名为options的手册页中进行描述。
每一个手册页以标准选项(STANDARD OPTIONS)部分开始,它列出了这些标准属性所适用的标准选项。
但是,你得看一下options手册页的描述。
作为对比,本书中的表格列出所有控件的属性。
23.5Tk命令总结
下面的表格列出了由Tk所加的TCL命令。
表格中的页码是命令的主要参考,同时在索引中也有其它参考。
23.5.1控件命令
表23-1列出了创建控件的命令。
在Tk中有18种不同的控件,虽然其中的4种是按钮的变体,5种专用于不同风格的文本显示。
23.5.2控件操纵命令
表23-2列出了操纵控件并提供像输入焦点、事件绑定、布局管理相关联的功能的命令。
23.5.3支撑过程
表23-3列出了一些实现标准对话框、可选菜单和其它功能的支撑过程。
23.6其它控件集
本书描述了由核心Tk发布版本所提供的控件集。
也有些其它Tk的控件集。
一些由TC L过程实现,它将基本控件组成有用的组合(如BWidgets)。
其它是由基于C的控件(如Tix和BLT)组成的。
一些更流行的控件集列在这里:
23.6.1BLT
George Howlett创建了BLT。
它包括一个可以有效支持大型数据集的主要图表控件。
也包括标签笔记本和树形视图控件。
其忙录控件用一个透明的仅显示一个监视光标的控件覆盖应用程序,当应用程序忙于做某事且你不想接受鼠标点击时,这个是非常方便的。
这是一个基于C的工具包。
/projects/blt/
23.6.2Tix
Tix由Ioi Lam所创建,现在由一些志愿者组成的小组所支持。
它包括几个控件和一个在TCL中创建控件的基础组织。
特色包括气球提示、标签窗口、窗格窗口和一个层次游览器。
虽然它包含一些由TCL组合成的控件,但还是一个基于C的工具箱。
/
23.6.3[incr Tk] and [incr Widgets]
[incr Tk]是一个使用[incr Tcl]对象系统来创建组合控件的基于C的框架。
它包括很多控件,从简单的标签项控件到HTML显示控件。
这些工作在Chad Smith的书[inc r Tcl] from the Ground Up (Osborne-McGraw Hill, 1999).中有描述。
23.6.4BWidgets
BWidgets是一个基于TCL控件集。
包括多种组合控件,包括标签记事本、组合框、层次游览器。
位于标准TCL库的WEB站点:
/projects/tcllib
23.6.5TkTable
TkTable是一个网格几何管理器和几个基于文本控件的组合。
它使一些像电子数据表这样的表列数据很容易的显示出来,同时也提供了很多对单元格和其数据格式化的控制。
/projects/tktable
24TK例子
本章通过一系列较短的子来介绍Tk。
ExecLog在后台运行一个程序并显示其输出。
浏览器的例子从书中显示TCL例子。
Tcl Shell例
子让你键入TCL命令并在一从此从解释器中执行。
Tk提供了一种快速有效的方式产生来用户界面。
在本章我们通过一系列小例子让你对你能做什么有一个感性的认识。
这里掩盖了一些细节并在后面进行详细的描述。
特别地,pack布器管理器在第25间涵盖,事件绑定在第29间讨论。
Tk控件会在后面的章节中进行详细的讨论。
24.1ExecLog
我们的第一个例子提供了一个用exec命令运行另一个程序的简单用户界面。
此界面包括两个按钮(Run it和Quit)一个用于输入命令的entry控件,一个用于记录程序运行结果的文本控件。
此脚本在一个管道中运行这个程序,并使用fileevent命令来等待输出。
此结构使程序在执行时用户界面仍然保持响应。
比如你可以运行make,并使结果保存在log中。
完整的例子先给出,其中的命令在后面详细的讨论。
24.1.1例24-1使用exec记录一个程序的输出
24.1.2窗口标题
第一个命令设置出现在由窗口管理器实现的标题栏。
记住那个点(也就是.)就是主窗口的名字:
wm命令与窗口管理器交互。
窗口管理器就是让你打开、关闭、调节
窗口大小的程序。
它为窗口实现标题栏,可能也有一些用来关闭或调节大小的小按钮。
不同的窗口管理器有完全不同的外表;此图显示了来自X窗口管理器twm的标题栏。
24.1.3按钮的框架
创建一个框架用来装出现在界面顶部的控件。
此框架有一个为控件周围提供一些空间的边界:
框架位于主窗口的顶部。
默认的堆叠边是顶部,所以这里-side t op是多余的,但是使用是为了清晰化。
-fill x堆叠选项使框架将主窗口整个宽填满:
24.1.4命令按钮
创建了两个按钮:一个用来运行命令,另一个用来退出程序。
它们的名字.top.quit和.top.run暗示它们是.top框架的子控件。
这个影响pack命令,它默认将控件放置在父控件中:
24.1.5标签与Entry
标签和entry也作为.top框架的子控件创建。
标签创建时在X方向没有填充空间,以便可以放置在后面的entry控件。
Entry控件的大小根据字符来确定。
Relief属性给予entry控件一些外观使它在显示上分开来。
Entry控件的内容关联到TCL变量command上:
标签和entry控件停靠在.top框架内部的左边。
Entry控件的另外停靠参数允许它扩展其停靠空间并在显示上填充其额外的空间。
停靠空间和显示空间的区别在339页第25章中讨论:
24.1.6按键绑定与焦点
Entry控件的按键绑定提供了激活应用程序功能的另外一种方式。
Bind命令将TCL命令与一个指定控件的事件关联起来。
当用户在键盘上按回车键时,<Return>事件会被触发。
当Control键已经按下时,字母c被键入时<Control-c>事件被产生。
为使事件到达entry控件. top.cmd,必须将输入焦点给这个控件。
默认情况下,当用鼠标左键点击它时就得到焦点。
对于焦点跟随鼠标模式的用户来说显示使用focu s命令是非常有益的。
当鼠标在主窗口上时,用户可以向entry中打
字:
24.1.7可调大小文本和滚动条
创建一个文本控件并连同一个滚动条停靠到一个主框架中。
文本控件的宽和高分别用字符和行数来指定。
文本的setgrid属性是打开的。
这限制其大小调节以便使整数行、平均大小的字符能被显示。
在Tk中,滚动条是一个单独的控件,它可以使用和这里相同的设置连到不同的控件上。
当文本控件被修改时,文本的yscrollcommand 更新滚动条的显示,且当用户操纵滚动行时,滚动条的command滚动与其关联的控件:
创建一个Tk控件的副作用是创建了一个操作此控件的新的TCL命令。
此TCL命令与控件的路径名相同。
在此脚本中,文本控件命令,也就是.t.log,在许多地方需要。
可是,将一个重要控件的路径名存到一个变量中是一个好主意,因为如果你重新组织用户界面,路径名可
以改变。
这样做的缺点是你必须在过程内部要用global声明此变量。
为了证明这种方式此例中的变量log就是用于这个目的。
24.1.8Run过程
Run过程开始在命令entry中指定的程序。
因为entry的textv ariable属性,此值在全局command命令中可以得到,命令在管道中运行以便它在后台运行。
Open命令参数的前导符|表示创建一个管道。
Catch命令作为非法命令输入的保护。
变量input设置成错误消息或正常的open返回的文件描述符。
程序像这样开始:
从管道中捕获错误
管道通过cat程序从命令转移错误输出。
如果你不像这里使用cat,当管道关闭时管道中的错误会输出弹出一个错误消息。
在本例中,令人尴尬的是如何区分程序产生的错误和由于Stop过程实现的方式所产生的错误。
不但如此某些程序间隔正常和错误输出,而且你可能想按顺序查看错误输出而不是在最后一下子查看。
如果管道成功打开,则使用fileevent命令设置一个回调函数。
当管道产生输出时,脚本可以从中读出数据。
Log注册为当管道可读时被调用的过程:
Command(或错误消息)被插入到log中。
这个通过使用文本控件的名字来实现,名字以一个TCL命令存储在log变量中。
命令的值被追加到log,并加了一个新行以便其输出可以出现在下一行。
文本控件的insert函数带有两个参数:一个标记和一个在此标记上要插入的字串。
符号标记end代表文本控件内容的末尾。
运行按钮在程序开始后变成停止按钮。
这个避免界面的混乱,也证明了Tk界面的动态特性。
再次,因为这个按钮在脚本中几个不同的地方使用,其路径名已经被存储在变量中but:
24.1.9Log过程
当管道中有数据可读或达到文件末尾时,Log过程就被激活。
此条件首先被检查,且Stop过程被调用来进行清理。
否则,一行数据被读取并插入到log中。
文本控件的see操作用来将文本的视图定位以使新行对用户可见:
24.1.10Stop过程
Stop过程通过关闭管道来终止程序。
Close用一个catch进行包装。
这个可以制止当进程上的管道过早地关闭时产生的错误。
最后,按钮被恢复到其运行状态以便用户可以运行另一个命令:
在多数情况下,关闭管道等同于杀死任务。
在UNIX中,这个将导致下一次向其标准输出写操作时发送一个SIGPIPE信号到程序。
没有一个杀死进程的内嵌方式,但是你可以exec UNIX的kill程序。
Pi d命令返回管道中进程的ID:
如果你需要对另一个进程更复杂的控制,你应该看一下在Explr ing Expect(Don Libes, O'Reilly & Associates, Inc., 1 995)中描述的TCL的expect扩展。
Expect提供了对交互式程序的强有力的控制。
你可以写发送输入到交互式程序并对其输出进行模式匹配的TCL脚本。
Expect被设计为自动使用交互式应用为目的的程序。
24.1.11跨平台讨论
这个脚本可以在UNIX和Windows上运行,但是不能运行在Maci ntosh上因为那没有exec命令。
另一个问题是取消任务的<Control -c>的绑定。
这是类UNIX的,但Windows用户指望<Escape>来取消一项任务,Macontosh用户指望<Command-period>。
Platform_
CancelEvent定义了一个虚拟事件、<<Cancel>>,Stop绑定其上:24.1.12例24-2一个指定平台的取消事件
Tk也已经也定义了虚拟事件。
event命令和虚拟事件在446页中描述。