3. Tcl 和 Tk 基础

Tcl 由作用于数据的命令构建而成,这些命令接受许多选项来指定每个命令的执行方式。每个命令由命令名称以及一个或多个用空格分隔的单词组成。因为 Tcl 是解释型语言,所以可以通过其 shell 命令 tclsh 交互式运行,也可以作为脚本非交互式运行。当 Tcl 以交互方式运行时,系统会对输入的每个命令做出响应,如下例所示。您可以通过简单地打开终端并输入命令 tclsh 来尝试 tclsh。

$ tclsh
% set a 35
35
% expr 35 * $a
1225
% puts "35 * a is: [ expr 35 * $a ]"
35 * a is: 1225
% exit
$

前面的例子说明了 Tcl 语言的几个方面。第一行,set a 35 使用 set 命令将 35 赋值给变量 a。第二行使用 expr 命令计算 35 乘以变量 a 的值的结果。请注意,与 Perl 和 Bash 类似,Tcl 需要使用美元符号运算符来获取变量的值。表达式 [ expr 35 * $a ] 周围的方括号指示解释器对表达式执行命令替换,将其添加到字符串的其余部分,并使用 puts 命令将字符串打印到 Tcl 的默认输出通道,标准输出。

Tcl 的窗口 shell,Wish,是一个解释器,它可以从标准输入或文件中读取命令,并使用 Tcl 语言解释它们,并从 Tk 工具包构建图形组件。与 tclsh 类似,它可以交互式运行。

要以交互方式调用 Wish,请在您的系统上启动 X,打开终端,并在命令提示符下键入 wish。如果您的环境设置正确,这将启动一个空的根窗口并在您的终端中启动窗口 shell。以下示例是一个两行脚本,它是可以使用 wish 创建的最简单的程序之一

$ wish
% button .submit -text "Click Me" -command { puts "\nHello World" }
.submit
% pack .submit

让我们分析这两行代码

button .submit -text "Click Me" -command { puts "\nHello World" }:

button 命令使您能够创建和操作 Tk 按钮小部件。与所有 Tk 小部件一样,语法是 button .name [-option value] [-option value] ...。包围 puts 命令的花括号允许您将文本字符串 "Hello World" 嵌套在命令内部,而无需执行任何变量替换。其他基本小部件包括以下内容:label、checkbutton、radiobutton、command、separator、entry 和 frame。单击按钮几次以验证它是否有效。

pack .submit

pack 命令告诉 Tk packer 几何管理器将窗口名称作为主窗口 . 的从属窗口进行打包,主窗口 . 始终由字符 . 引用。与我们将看到的其他 Tk 小部件命令一样,语法是 pack .name [-option value] [-option value]

虽然前面的示例非常简单,但更高级的示例也几乎同样容易构建。请看下面的脚本,该脚本为 apachectl 创建了一个简单的图形前端(请注意,此示例旨在作为脚本运行,而不是从 shell 交互式运行。您需要将脚本的权限设置为可执行,并以有权启动和停止 apache 的用户身份运行此脚本)

#!/usr/bin/wish

set apachectl "/usr/local/apache/bin/apachectl"
global apachectl

proc start {} {
  global apachectl
  exec $apachectl start & 
}

proc stop {} {
  global apachectl
  exec $apachectl stop &
}

proc restart {} {
  global apachectl
  exec $apachectl restart &
}

proc screen {} {
  frame .top -borderwidth 10
  pack .top -fill x	
  button .top.start -text "Start" -command start
  button t.op.stop -text "Stop" -command stop
  button .top.restart -text "Restart" -command restart
  pack .top.start .top.stop .top.restart -side left -padx 0p -pady 0
}
screen

此脚本介绍了一些新概念。让我们逐行查看其中的一些概念

set apachectl "/usr/local/apache/bin/apachectl"
global apachectl

正如我们之前看到的,set 命令用于为变量赋值。与前面的示例一样,语法很简单:set variable_name value。为了使变量可用于我们在此程序中创建的 Tcl 过程,我们需要将 apachectl 变量导入到每个过程中。这可以使用 global 命令来完成,该命令将命名变量添加到给定过程的本地命名空间。global 命令接受一个或多个变量作为参数,并将命名变量分配给程序中使用的每个过程。Global 也用于导出在过程的本地命名空间内声明的变量。

proc start {} {
  global apachectl
	  exec $apachectl start &
}

Tcl 中的过程是使用 proc 命令创建的。proc 命令采用以下形式:proc name {args} {body},其中 name 是过程的名称。Args 是过程接受的形式参数,body 是过程的主要代码。过程的执行方式与 Tcl 中任何其他命令的执行方式相同。

我们当前正在处理的脚本由 4 个过程组成。前 3 个过程(start、stop、restart)只是将 apachectl 变量导入到本地命名空间并作为后台进程执行基本的 apachectl 命令,而第 4 个过程 "screen" 使用 packer 构建基本屏幕并调用每个函数。

让我们仔细看看 screen 过程

  
proc screen {} {
  frame .top -borderwidth 10
  pack .top -fill x	
  button .top.start -text "Start" -command start
  button .top.stop -text "Stop" -command stop
  button .top.restart -text "Restart" -command restart
  pack .top.start .top.stop .top.restart -side left -padx 0p -pady 0
}

screen 过程首先使用 frame 命令来构建基本框架,该框架将包含过程后面指定的按钮。正如本示例所示,从属小部件通过在其前面加上其主部件的名称和一个 "." 来指定。主部件必须在从属部件可以使用它们之前就已经打包好,因此我们在指定 button 命令之前打包框架 .top,并告诉它沿 x 轴填充。

最后,我们使用 button 命令创建 3 个按钮作为 .top 的从属按钮,传入在按下按钮时要执行的相应过程,并分别使用 -command-text 参数添加文本标签。