使用 Tcl 来组织桌面

发表于:2007-05-25来源:作者:点击数: 标签:
大多数图形用户界面 (GUI) 桌面为您提供了丰富的配置选项。您可以通过编写脚本的方式对一组 GUI 小部件进行配置,这样可以超出桌面通常所能完成的配置工作。 大多数计算机用户主要通过某种形式的图形用户界面 (GUI) 来进行与工作站的交互。在 Microsoft Wind
大多数图形用户界面 (GUI) 桌面为您提供了丰富的配置选项。您可以通过编写脚本的方式对一组 GUI 小部件进行配置,这样可以超出桌面通常所能完成的配置工作。

大多数计算机用户主要通过某种形式的图形用户界面 (GUI) 来进行与工作站的交互。在 Microsoft® Windows® 的世界里,对这种界面进行了严格的控制。UNIX® 世界则与之相反,为实现不同的 GUI 提供了真正的自助方式,并且这些 GUI 的功能各不相同。这些 GUI 通常被称为窗口管理器,因为它们占用了 X-Windows 细节层上面的一层,并且它们对窗口进行管理。

UNIX 通常提供了充分的自由和选择系统的工作方式的权利。不同的个性类型需要不同的系统功能,UNIX GUI 则为每个用户都准备了相应的特性。它们从最低限度的窗口管理器,如 twm,到大型的且功能齐全的工具,如 GNOME 和 KDE (K Desktop Environment)。其中包括了大量的、各种形式的其他版本和功能。(要查看目前最常用的窗口管理器列表,请参阅参考资料部分。)

您可能需要以编写脚本的方式对桌面进行控制,以便利用相应的功能编写程序,而无需花费大量的时间来学习如何完成该项任务。或者,您可能更喜欢可编程方式的窗口管理器,这样您就可以像控制命令行接口那样来控制窗口。最低限度的窗口管理器是可以同时满足这两种需求的一个不错的选择,它运行于功能强大的窗口管理器之上,仅允许您轻松灵活地完成脚本编写工作。

Tcl/Tk 可以为您提供帮助

该工具最初由 University of California, Berkeley 的 John Ousterhout 博士开发,后来由 Sun Microsystems 和 Scriptics 对其进行了完善,工具命令语言 (Tool Command Language) 和 Tk GUI 工具包 (Tcl/Tk) 脚本语言提供了一种以最少的工作量来编写 GUI 小部件的简单而完美的方式。

编写计算机程序来完成某项任务通常至少涉及两方面的问题:程序的形式以及程序的工作方式。Tcl/Tk 编程语言努力使程序的形式 问题变得更加容易,它使得您可以轻松地通过脚本编写 GUI 小部件(如窗口和按钮),并将其关联于相应的过程(即程序的工作方式 的问题)。

需要做些什么工作?

干净而整洁的桌面,这在虚拟和现实世界中都是很有好处的。整洁 意味着仅在桌面上准备一些可以完成大量工作的图标。(这些图标有时也称为咖啡图标,点击这些图标后,在其启动所需的一组程序时,您可以起身去倒杯咖啡。)将几个程序的执行组合成仅具有一个图标的单个任务,这是一种很好的方法。

例如,要撰写类似本文这样的文章,您可以用脚本编写单个图标,当点击了这个图标后,打开一个工作所需的 xterm、一个编辑 XML 文件的文本编辑器以及一个显示该文章的浏览器。在单击这个图标后,启动了所有这些工具,您可以按照需要对其进行配置,包括合适的屏幕大小、工作目录集和所有打开的并可对其进行操作的文件。这就是编写脚本!

您可以使用 bash shell 脚本来实现相同的目的并将脚本关联于一个桌面图标,但是 Tcl/Tk 为 GUI 方面提供了更好的接口。

作者的助手

清单 1 介绍了一个 Tcl/Tk 程序,它实现了前一节中所描述的情况,即单击一个图标后启动所有的相关任务。除了启动 xterm、编辑器和浏览器之外,它还提供了一个按钮,您可以在任何时候单击该按钮来运行 IBM 提供的一个脚本,以将文章从 XML 转换为 HTML。


清单 1. 作者的助手
#!/usr/bin/wish -f
            # 1 -- How should it look?
            set PageTitle "IBM developerWorks Articles -- Studio B"
            set InitDir "/home/bill/StudioB/developerworks"
            set ChooseDir "Choose an Article Directory"
            frame .rc -borderwidth 2
            wm title . $PageTitle
            wm resizable . 0 0
            button .rc.b -width 20 -text "Rebuild Article" -command {rebuild-article}
            button .rc.c -width 20 -text "Exit" -command {exit}
            pack .rc
            pack .rc.b
            pack .rc.c
            grid .rc.b .rc.c -sticky ew
            # 2 -- What should it do?
            proc rebuild-article {} {
            exec ./dw-transform.sh &
            }
            wm geometry . =336x32+0+707
            set dir ""
            while {$dir == ""} {
            set dir [tk_chooseDirectory             -initialdir $InitDir             -title $ChooseDir]
            }
            cd $dir
            exec nedit -geometry 150x48+0+0 index.xml &
            exec konsole &
            exec opera -geometry 1024x680+0+0 index.html &
            

您可以按下鼠标左键从屏幕搜集这段代码,并搜集其中的所有内容。然后启动您最喜爱的编辑器,单击鼠标中键将这段文本粘贴到编辑器中。将文件保存为 article.tcl,并使用 chmod 命令使其具有可执行权限:

$ chmod +x article.tcl
            

因为窗口管理器和硬件可能有所不同,甚至可能没有鼠标中键,所以这里的说明可能与您所需要的并不完全相同。在这种情况下,您可以找人提供帮助。

下一部分将对该程序中的部分内容进行研究。

变量

代码的第一部分中使用了传统的 UNIX #! 字符串来运行名为 wish 的 Tcl/Tk 解释器。-f 开关告诉 wish 运行该脚本,然后退出。

在这之后是一段注释,用 # 表示,以 How should it look? 作为代码块的开始,紧随其后对字符串变量进行了设置。像这样将文本安排在代码的上方,通常是一个很好的编程习惯:

#!/usr/bin/wish -f
            # 1 -- How should it look?
            set PageTitle "IBM developerWorks Articles -- Studio B"
            set InitDir "/home/bill/StudioB/developerworks"
            set ChooseDir "Choose an Article Directory"
            

Tk GUI 代码

这一小块代码创建了一个带有两个并排的按钮的窗口。就简洁性而言,在定义窗口和小部件方面,很难有能够超过 Tk 的:

frame .rc -borderwidth 2
            wm title . $PageTitle
            wm resizable . 0 0
            button .rc.b -width 20 -text "Rebuild Article" -command {rebuild-article}
            button .rc.c -width 20 -text "Exit" -command {exit}
            pack .rc
            pack .rc.b
            pack .rc.c
            grid .rc.b .rc.c -sticky ew
            

frame 命令创建了一个称为 .rc 的窗口,其边界宽度为 2 个像素。wm 命令告诉基础窗口管理器使用 PageTitle 对最前面的窗口(. 通常表示最前面)进行命名,接下来的 wm 命令禁止用户调整其大小。然后对两个按钮进行了定义,并将它们放入到水平的网格中。

按钮代码

IBM 提供了一段程序来将文章(以 XML 格式编写)转换为外观类似于 developerWorks 站点这样的 Web 页面 (HTML)。当您单击同名的按钮时,rebuild-article 过程调用了这段脚本。在该脚本运行结束后,将显示一个对话框,用以描述将 XML 转换为 HTML 的过程中所进行的操作,其中包括相应的错误消息(如果有的话)。如果这段程序告诉您已经创建了 index.html 文件,那么您可以单击 OK,让浏览器获得焦点,并刷新页面以查看新的文档:

proc rebuild-article {} {
            exec ./dw-transform.sh &
            }
            

启动代码

在启动代码中,wm geometry . =336x32+0+707 将桌面扩展窗口放置在 1024 x 768 桌面的底部。然后,该段代码打开了一个对话框,它允许您选择需要进行转换的文章。最后,它将文章的目录作为当前的工作目录,并启动编辑器 (nedit)、xterm (konsole) 和浏览器 (Opera)。在任务开始执行前对所有的这些内容进行正确的配置:

wm geometry . =336x32+0+707
            set dir ""
            while {$dir == ""} {
            set dir [tk_chooseDirectory             -initialdir $InitDir             -title $ChooseDir]
            }
            cd $dir
            exec nedit -geometry 150x48+0+0 index.xml &
            exec konsole &
            exec opera -geometry 1024x680+0+0 index.html &
            

对于这个 Tcl/Tk 程序,可以在很多方面进行改进。添加创建新文章的按钮或将所有的文章备份到存档的按钮,这些都是值得进行的改进,并且 Tcl/Tk 让您可以轻松地完成这些工作。您还可以设置首选编辑器、xterm 和浏览器。您可以随意地对其进行实验,绝不要将这个桌面扩展仅用于为 IBM 撰写文章:可以对其进行修改,以启动一个编程环境或 Web 技术环境。

一个 50 行代码的科学计算器

现在,您将通过一个更加复杂的 Tcl GUI 程序来组织桌面:通过仅 50 行代码编写的一个科学计算器(请参见清单 2)。这个计算器可以对通过键盘或 GUI 按钮输入的表达式进行计算。如果您输入一个无效的表达式,其文本将变为红色。与清单 1 中的程序一样,您可以将这段代码从屏幕搜集到一个文件,并将其保存为 calc.tcl,使用 chmod 将其权限修改为可执行,然后运行该程序。


清单 2. 50 行代码的计算器
            #!/usr/bin/wish -f
            # 1 -- How should it look?
            set cflag 0; set nextkey 0
            wm title . "50-Line Calculator"
            wm resizable . 0 0
            grid [entry .display -textvariable expression -justify right] -columnspan 6
            focus .display
            bind .display <Return> equals; bind .display <KP_Enter> equals
            foreach row {
            {7 8 9 + -  sin(}
            {4 5 6 * /  cos(}
            {1 2 3 ( )  tan(}
            {C 0 . = Pi log(}
            } {
            foreach key $row {
            switch -- $key {
            C       {set string {set cflag 1; set expression ""}}
            Pi      {set string pi}
            =       {set string equals}
            default {set string "press $key"}
            }
            lappend keys [button .[incr nextkey] -text $key -command $string]
            }
            eval grid $keys -sticky we
            set keys [list]
            }
            # 2 -- What should it do?
            proc press {key} {
            if $::cflag {
            set ::expression ""
            if ![regexp {[0-9().]} $key] {set ::expression $::results}
            .display configure -fg black
            .display icursor end; set ::cflag 0
            }
            .display insert end $key
            }
            proc pi {} {
            if $::cflag {set ::expression ""}
            lappend ::expression "3.14159265"
            .display icursor end; set ::cflag 0
            }
            proc equals {} {
            regsub {=.+} $::expression "" ::expression
            if [catch {lappend ::expression =             [set ::results [expr             [string map {/ *1.0/} $::expression]]]}] {
            .display configure -fg red
            }
            .display xview end; set ::cflag 1
            }
            

这段代码中存在一些假像,即将长代码行划分为较短的代码行,但是您可以看到,Tcl/Tk 是一种非常简洁的语言。允许您使用这么少的代码行创建如此复杂的 GUI 程序的编程语言并不多见。

主窗口

除了用来运行解释器的常规的 #! 代码之外,还设置了一些变量:cflag 用来控制主数据条目小部件 .display 如何搜集相应的字符,而 nextkey 则是在构建键数组时所使用的索引。然后,与前一个程序相同,设置窗口标题文本并禁止用户调整其大小。

在这之后,定义了计算器的 display 小部件。这里有几个内容需要说明一下:与大多数计算器的外观一样,文本通常是右对齐的,所以从控件的右边开始搜集键值,并向左边进行滚动。动词 focus 使 display 获得焦点,所以您可以使用键盘或 GUI 按钮来输入表达式。然后,将代码绑定到按下计算器的 Enter 键时或键盘 Enter 键按下时需要执行的操作,这样就完成了 display 小部件:

#!/usr/bin/wish -f
            # 1 -- How should it look?
            set cflag 0; set nextkey 0
            wm title . "50-Line Calculator"
            wm resizable . 0 0
            grid [entry .display -textvariable expression -justify right] -columnspan 6
            focus .display
            bind .display <Return> equals; bind .display <KP_Enter> equals
            

计算器的小键盘

这段代码动态地构建了计算器小键盘上相应的键,通过 display 中的文本定义了每个按钮,在 C、Pi 和 = 键的情况下,当按下这些键时需要执行一个特殊的过程。像 Tcl/Tk 这样,允许您使用这么少的代码行来定义这么多小部件的 GUI 程序的编程语言并不多见。

foreach row {
            {7 8 9 + -  sin(}
            {4 5 6 * /  cos(}
            {1 2 3 ( )  tan(}
            {C 0 . = Pi log(}
            } {
            foreach key $row {
            switch -- $key {
            C       {set string {set cflag 1; set expression ""}}
            Pi      {set string pi}
            =       {set string equals}
            default {set string "press $key"}
            }
            lappend keys [button .[incr nextkey] -text $key -command $string]
            }
            eval grid $keys -sticky we
            set keys [list]
            }
            

计算器的功能

仅通过 3 个过程,就可以定义计算器所需的所有功能。请记住,在该程序运行时,操作集中在 display 小部件的内容上。当按下 = 键或 Enter 键时,expr 函数将对这些内容进行计算。

当按下大多数 GUI 按钮时,将使用 press 过程。其目的是将该按钮的名称文本添加到 display 和 expression 字符串的结尾处,而这个表达式将在以后进行计算。当设置了 cflag 时,将清除该表达式,为 next 表达式的输入和计算做准备:

# 2 -- What should it do?
            proc press {key} {
            if $::cflag {
            set ::expression ""
            if ![regexp {[0-9().]} $key] {set ::expression $::results}
            .display configure -fg black
            .display icursor end; set ::cflag 0
            }
            .display insert end $key
            }
            

pi 过程将 pi 的值插入到 display 和 expression 变量:

proc pi {} {
            if $::cflag {set ::expression ""}
            lappend ::expression "3.14159265"
            .display icursor end; set ::cflag 0
            }
            

当按下 = 键或其中一个 Enter 键时,将执行 equals 过程。通过使用 Tcl/Tk 的功能强大的 expr 动词和完成计算任务的数学代码库,实现了对表达式的计算,并且将结果保存到了 results 变量。如果发生输入错误,如不匹配的括号,将通过 expr 抛出 catch 错误代码,并且将 display 的颜色设置为红色:

proc equals {} {
            regsub {=.+} $::expression "" ::expression
            if [catch {lappend ::expression =             [set ::results [expr             [string map {/ *1.0/} $::expression]]]}] {
            .display configure -fg red
            }
            .display xview end; set ::cflag 1
            }
            

根据 expr 动词的相关文档的显示,它可以处理许多其他的数学函数,如 asinacosatan、指数、地板函数等等。您可以使用键盘输入这些表达式,然后观察 expr 的工作,现在您已经有了足够的知识来修改该计算器代码,以添加支持这些函数的按钮。要了解更多的相关信息,请访问参考资料部分中列举的 Tcl/Tk 关键字。

纯 Tcl 桌面

许多人都沉迷于使用 Tcl/Tk 来编写 GUI 脚本的强大功能,他们已经编写出了各种纯 Tcl/Tk 的编辑器、浏览器、文件和桌面窗口管理器。参考资料部分中包括了其中部分内容的列表。

结束语

每一项勾画出现代世界美好生活的杰出发明的出现,都是因为有的人不满足于现状并且决定对其进行积极的改变。您可以通过技术来改进世界,通过编写脚本为工作站设计新的桌面并体会其中的乐趣,这可能会开启通往其他具有深远意义的观念的大门。祝您编写脚本愉快!

原文转自:http://www.ltesting.net