Tcl/Tk 烹调书 - Tk 基础


第 3 步: 显示属性-值对

脚本

向 appl1.tcl 添加如下行[为了清晰和良好的编程实践,在脚本的顶部(就是在 #!/usr/bin/wish 行的下面)放置全局声明,声明过程之后立即在过程体的顶部放置全局声明。任何初始化都放置在设置或重置脚本中的值之前。]


global aList vList

set aList {}
set vList {}
set maxl 0

set b [.rc.b config]

foreach e $b {
	lappend aList [lindex $e 0]
	lappend vList [lindex $e 4]
	set a [lindex $e 0]
	if { [string length $a] > $maxl } {
		set maxl [string length $a]
		}
	}

第一行设置了两个全局变量 aList 和 vList 接着下面两行初始化这两个变量的值为空列表。后面的一行设置一个变量 maxl 为零。

命令 set b [.rc.b config] 调用组件命令 .rc.b 得到它的当前的配置选项的列表被把这个列表赋给变量 b。注意这个 b 是一个列表的列表。每个嵌套的(nested)列表都包含象 -background 这样的配置选项并跟着相关的信息,其中第五项是值。

首先 foreach 循环访问列表"b"的嵌套列表"e"

  1. 获得选项(在列表 e 的第0个索引上),把它添加到"aList"上。
  2. 获得当前选项的值(在列表 e 的第5个索引上)。
  3. 计算选项字符串的最大长度并赋给 maxl。这随后被用于定位右对齐的标签字符串建立有整齐的外观样式的界面。

现在你需要建立一个界面来显示这些成对的值。由下面的脚本完成:


set i 0

frame .rc.fff -height 40 

pack .rc.fff
foreach a $aList {
	set ff [frame .rc.fff.sub$i]
	pack $ff
	label $ff.lab -text $a -width $maxl -anchor e
	entry $ff.ent
	bind $ff.ent  [list reJig .rc.b $a]
	$ff.ent insert 0 [lindex $vList $i]
	pack $ff.lab $ff.ent -side left -in $ff
	incr i
	}

设置一个计数器 "i",并初始化成零。frame .rc.fff -height 40 建立一个 .rc 的子框架 .rc.fff,高度是 40 象素,接着 pack .rc.fff 缺省的在按钮 .rc.b 的下面包装它。

对于每一个列表"aList"的元素 "a" 

  1. 建立一个名字中包含计数器"i"的框架(例如 .rc.fff.sub0) 作为 .rc.fff 的子框架并把它赋给变量 "ff" {注意这是给出一个常组件名的捷径}。包装这个子框架。
  2. 在由"ff"给出的框架中建立一个文本是配置选项的标签属性。标签属性的宽度设置成 "maxl"的值来建立同一的标签大小。标签被固定(anchor)在框架的东侧(the east of the frame)来确定外观。
  3. 建立一个录入组件,它的名字是向"ff"的值添加 .ent。用录入组件显示一行可编辑的文本串。
  4. 建立一个在录入组件中的事件(用户键入一个字符串并敲回车键)上的绑定。[list reJig .rc.b $a] 替换 "a" 的值并建立要被调用的脚本{一个命令,用".rc.b" 和 "a "作为参数调用过程 reJiG}。
  5. 属性的当前值被插入到录入组件中。
  6. 标签和录入组件被从左到右的包装进用"ff"给出的它们的父组件中。
  7. 增加计数器的值

注意: 同任何 shell 编程语言一样, 在 Tcl/Tk 中完成特定结果有多种方式。例如脚本要指定绑定为 "reJig .rc.b $a",使用了 [list * * ] 确定完成了正确的变量替换并且生成一个正确的列表结构,列表的元素一起形成一个单一的命令。

如果你尝试 {reJig .rc.b $a},因为"a"在花括号中你将发现它 没有被它的值所替换。结果是过程 reJig 将收到字符串 $a 而不是 a 的值。

还要注意因为组件的有层次的名字唯一的标识一个组件,.rc.fff.sub0.ent 与 .rc.fff.sub1.ent. 是不同的。

在脚本 appl1.tcl 中添加这些行并执行之将产生: