Tcl/Tk 烹调书 - 文本编辑器


第 3 步: 建立弹出式对话框

脚本

译者按:余修改了部分代码。

向 ed.tcl 添加下列语句,包含建立对话窗口和相关的行为的脚本的源代码。脚本在以下三个文件中,message.tcl, filesel.tcl 和 popup.tcl:



#source some of the auxillary scripts we will be using
#note these can be source in appropriate procedures too

source filesel.tcl

source message.tcl

source popup.tcl


文件选择框的使用

对于这个编辑器,在用户要指定想打开文件的名字,或把文本组件中的文本保存到的那个文件的名字的时候,弹出文件选择框。
    

译者按:

filesel.tcl 脚本使用了依赖于 *NIX 的 ls 命令,余将其忽略,使用了 Tk 内置的 tk_getOpenFile 命令和 tk_getSaveFile 命令。其格式为:tk_getOpenFile ?option value ...? ,tk_getSaveFile ?option value ...? 。
 

过程 tk_getOpenFile 和 tk_getSaveFile 弹出一个对话框供用户选择要打开或保存的一个文件。tk_getOpenFile 通常与在 File 菜单中的打开命令相关联。它的功能是让用户选择一个现存的文件。如果用户输入了一个不存在的文件,对话框向用户给出一个错误提示并要求用户给出替代的选择。如果一个应用允许用户建立新文件,它应该为此提供一个独立的 New 菜单命令。 

tk_getSaveFile 命令通常与在 File 菜单中的 Saveas 命令相关联。如果用户输入了一个不存在的文件,对话框提示用户确认是否覆写这个现存的文件。

 

文件选择框脚本是捐献的软件并有细微的修改。这个脚本在本书中的代码子目录下的 ch3 中,名字是  filesel.tcl。把这个文件复制到当前的工作路径。读者应当可以把它作为一个对立的单元使用。

文件选择框很简单,如下:

警告消息
 

译者按:

余忽略了 mes.tcl ,使用了 Tk 内置的 tk_messageBox 命令。其格式为:tk_messageBox ?option value ...?  。

这个过程建立并显示一个消息窗口,有有特定于应用的消息,一个图标和一系列按钮。在消息窗口中的每个按钮都由一个唯一符号名字来标识(参见它的手册页中的 -type 选项)。在弹出这个消息窗口之后,tk_messageBox 等待用户选择按钮中的一个。接着它返回选择的按钮的符号名字。

当用户选择了一个 "SaveAs" 选项但随后就改变了想法而取消这个文件选择框,弹出一个文本组件的内容将被以老文件名存储的警告消息。

下面的脚本的代码将被放置在文件 file mes.tcl 中:



proc showMessage {mess} {

toplevel .messpop -width 10c -height 4c
grab .messpop
wm title .messpop "Warning"
message .messpop.msg -relief raised -bd 2 -text $mess

button .messpop.okb -text OK \
	-com {destroy .messpop ; return 0}
pack .messpop.msg .messpop.okb -side top 
}

showMessage 接受一个消息字符串作为参数(过程实质上被参数化(parametrized)了,所以对所有你想对话的消息你都可以变化参数而使用相同的过程)。它显示一个用 Tk 命令 message 建立的消息组件,调用参数是作为输入传递进来的消息串。还包含一个 "OK" 按钮,它连接着在用户在按钮上点击时销毁这个顶层窗口的命令。

典型(Modal)交互

Tk 命令 toplevel 为应用建立一个顶层窗口。这个顶层窗口是应用的根(主)窗口的子窗口,但可被用作给应用增加的窗口。

顶层窗口也可以被用作弹出式消息窗口。在这种情况下,在建立弹出式消息窗口的过程中,给 Tk 命令 grab 的参数是消息窗口的名字。这将夺取键盘焦点来确保用户注意。在调用过程中,调用 Tk 命令 tkwait window ,参数是消息窗口名字。它在调用过程中挂起处理,直到用户同弹出窗口进行了必须的交互并显式的关闭(销毁)了它。在弹出或顶层窗口中任何 OK、DISMISS Cancel 按钮的命令中销毁它。

使用脚本建立这个消息窗口,用以警告一个文件将被覆盖,看起来如下:

查找和替换窗口

在用户打算在显示的文本上做查找和替换或标记或标记所有操作时,使用了第三个弹出窗口。注意这个标记是临时的并且不在文件中保存。


proc FindPopup {} {

global seltxt repltxt

toplevel .fpop -width 10c -height 4c

grab .fpop
wm title .fpop "Find Text"


label .fpop.lab1 -text "Find :           " 
place .fpop.lab1 -in .fpop -x 2 -y 6
entry .fpop.en1 -width 20 -relief sunken -textvariable seltxt
place .fpop.en1 -in .fpop -x 72  -y 6

label .fpop.lab2 -text "Replace :        "
place .fpop.lab2 -in .fpop -x 2 -y 50
entry .fpop.en2 -width 20 -relief sunken -textvariable repltxt
place .fpop.en2 -in .fpop -x 72 -y 50

menubutton .fpop.finb -text Find -menu .fpop.finb.menu
place .fpop.finb -in .fpop -x 2 -y 90
menu .fpop.finb.menu 
.fpop.finb.menu add command -label Forward -com {FindWord  -forwards $seltxt}
.fpop.finb.menu add command -label Backward -com {FindWord -backwards $seltxt}

menubutton .fpop.finrb -text "Find and Replace" -menu .fpop.finrb.menu
place .fpop.finrb -in .fpop -x 38 -y 90
menu .fpop.finrb.menu
.fpop.finrb.menu add command -label Forward  -com {ReplaceSelection -forwards}
.fpop.finrb.menu add command -label Backward -com {ReplaceSelection -backwards}

button .fpop.repall -text "Replace All" -com {ReplaceAll}
place .fpop.repall -in .fpop -x 150 -y 90

button .fpop.tagall -text "Tag All" -com {TagAll}
place .fpop.tagall -in .fpop -x 250 -y 36

button .fpop.dismis -text Dismiss -com {destroy .fpop}
place .fpop.dismis -in .fpop -x 250 -y 90


focus .fpop.en1
}

这个代码与那个消息框顶层窗口一样,同在建立主菜单的章节中曾经描述的相类似。注意命令 "place" 接受两个选项 "-x" 和 "-y",它们的值是整数(在这种情况下是象素)并要求打包器在由"-in"选项给出的组件之中的位置上放置这个组件。

在这个弹出窗口中菜单按钮 Find 、Find 和 Replace 都有下拉菜单来做向前和向后查找。这些过程在下一章中定义。如果你现在打算执行这个脚本并测试它,你可以注释掉在 -com 选项开始之前的行。这将停止 Tk 解释器对未定义命令的抱怨。

执行这个程序的最终结果应该是: