探索 Tcl/Tk 的基础构造,包括用户输入、输出、变量、条件评估、简单函数和基础事件驱动编程。
【资料图】
我写这篇文章的初衷源于我想更深入地利用基于 Tcl 的 Expect。这让我写下了以下两篇文章:通过编写一个简单的游戏学习 Tcl和通过编写一个简单的游戏学习 Expect。
我进行了一些Ansible自动化工作,逐渐积累了一些本地脚本。有些脚本我频繁使用,以至于以下循环操作变得有些烦人:
打开终端使用cd
命令跳转至合适的目录输入一条带有若干选项的长命令启动所需的自动化流程我日常使用的是 macOS。实际上我更希望有一个菜单项或者一个图标,能够弹出一个简单的界面接受参数并执行我需要的操作,这就像在 Linux 的 KDE 中一样。
经典的 Tcl 类书籍都包含了关于流行的 Tk 扩展的文档。既然我已经深入研究了这个主题,我尝试着对其(即wish
)进行编程。
虽然我并非一名 GUI 或者前端开发者,但我发现 Tcl/Tk 脚本编写的方式相当直接易懂。我很高兴能重新审视这个 UNIX 历史的古老且稳定的部分,这种技术在现代平台上依然有用且可用。
安装 Tcl/Tk对于 Linux 系统,你可以按照下面的方式安装:
$ sudo dnf install tcl$ which wish/bin/wish
而在 macOS 上,你可以通过Homebrew来安装最新版的 Tcl/Tk:
$ brew install tcl-tk$ which wish/usr/local/bin/wish
编程理念许多编写游戏的教程都会介绍到典型的编程语言结构,如循环、条件判断、变量、函数和过程等等。
在此篇文章中,我想要介绍的是事件驱动编程。当你的程序使用事件驱动编程,它会进入一个特殊的内置循环,等待特定的事件发生。当这个特定的事件发生时,相应的代码就会被触发,产生预期的结果。
这些事件可以包括键盘输入、鼠标移动、点击按钮、定时器触发,甚至是任何你的电脑硬件能够识别的事件(可能来自特殊的设备)。你的程序中的代码决定了用户看到了什么,以及程序需要监听什么输入,当这些输入被接收后程序会怎么做,然后进入事件循环等待输入。
这篇文章的理念并没有脱离我之前的 Tcl 文章太远。这里最大的不同在于用 GUI 设置和用于处理用户输入的事件循环替代了循环结构。其他的不同则是 GUI 开发需要采取的各种方式来制作一个可用的用户界面。在采用 Tk GUI 开发的时候,你需要了解两个基础的概念:部件widget和几何管理器geometry manager。
部件是构成可视化元素的 UI 元素,通过这些元素用户可以与程序进行交互。这其中包括了按钮、文本区域、标签和文本输入框。部件还包括了一些选项选择,如菜单、复选框、单选按钮等。最后,部件也包括了其他的可视化元素,如边框和线性分隔符。
几何管理器在放置部件在显示窗口中的位置上扮演着至关重要的角色。有一些不同的几何管理器可以供你使用。在这篇文章中,我主要使用了grid
几何来让部件在整齐的行中进行布局。我会在这篇文章的结尾地方解释一些几何管理器的不同之处。
这个示例游戏代码与我其他文章中的示例有所不同,我将它分解为若干部分以方便解释。
首先创建一个基本的可执行脚本numgame.wish
:
$ touch numgame.wish$ chmod 755 numgame.wish
使用你喜欢的文本编辑器打开此文件,输入下列代码的第一部分:
#!/usr/bin/env wishset LOW 1set HIGH 100set STATUS ""set GUESS ""set num [expr round(rand()*100)]
第一行定义了该脚本将通过wish
执行。接下来,创建了几个全局变量。这里我使用全部大写字母定义全局变量,这些变量将绑定到跟踪这些值的窗口小部件(LOW
、HIGH
等等)。
全局变量num
是游戏玩家要猜测的随机数值,这个值是通过 Tcl 的命令执行得到并保存到变量中的:
proc Validate {var} { if { [string is integer $var] } { return 1 } return 0}
这是一个验证用户输入的特殊函数,它只接受整数并拒绝其他所有类型的输入:
proc check_guess {guess num} { global STATUS LOW HIGH GUESS if { $guess < $LOW } { set STATUS "What?" } elseif { $guess > $HIGH } { set STATUS "Huh?" } elseif { $guess < $num } { set STATUS "Too low!" set LOW $guess } elseif { $guess > $num } { set STATUS "Too high!" set HIGH $guess } else { set LOW $guess set HIGH $guess set STATUS "That"s Right!" destroy .guess .entry bind all {.quit invoke} } set GUESS ""}
这是主要的猜数逻辑循环。global
语句让我们能够修改在文件开头创建的全局变量(关于此主题后面将会有更多解释)。这个条件判断寻找入力范围在 1 至 100 之外以及已经被用户猜过的值。有效的猜测和随机值进行比较。LOW
和HIGH
的猜测会被追踪,作为 UI 中的全局变量进行报告。在每一步,全局STATUS
变量都会被更新,这个状态信息会自动在 UI 中显示。
对于正确的猜测,destroy
语句会移除 “Guess” 按钮以及输入窗口,并重新绑定回车键,以激活 “Quit” 按钮。
最后的语句set GUESS ""
用于在下一个猜测之前清空输入窗口。
label .inst -text "Enter a number between: "label .low -textvariable LOWlabel .dash -text "-"label .high -textvariable HIGHlabel .status -text "Status:"label .result -textvariable STATUSbutton .guess -text "Guess" -command { check_guess $GUESS $num }entry .entry -width 3 -relief sunken -bd 2 -textvariable GUESS -validate all \ -validatecommand { Validate %P }focus .entrybutton .quit -text "Quit" -command { exit }bind all {.guess invoke}
这是设置用户界面的部分。前六个标签语句在你的 UI 上创建了不同的文本展示元素,-textvariable
选项监控给定的变量,并自动更新标签的值,这展示了全局变量LOW
、HIGH
、STATUS
的绑定。
button
行创建了 “Guess” 和 “Quit” 按钮,-command
选项设定了当按钮被按下时要执行的操作。按下 “Guess” 按钮执行了上面的check_guess
函数以检查用户输入的值。
entry
部件更有趣。它创建了一个三字符宽的输入框,并将输入绑定到GUESS
全局变量。它还通过-validatecommand
选项设置了验证,阻止输入部件接收除数字以外的任何内容。
focus
命令是用户界面的一项改进,使程序启动时输入部件处于激活状态。没有此命令,你需要先点击输入部件才可以输入。
bind
命令允许你在按下回车键时自动点击 “Guess” 按钮。如果你记得check_guess
中的内容,猜测正确之后会重新绑定回车键到 “Quit” 按钮。
最后,这部分设定了图形用户界面的布局:
grid .instgrid .low .dash .highgrid .status .resultgrid .guess .entrygrid .quit
grid
几何管理器被逐步调用,以逐渐构建出预期的用户体验。它主要设置了五行部件。前三行是显示不同值的标签,第四行是 “Guess” 按钮和entry
部件,最后是 “Quit” 按钮。
程序到此已经初始化完毕,wish
shell 进入事件循环,等待用户输入整数并按下按钮。基于其在被监视的全局变量中找到的变化,它会更新标签。
注意,输入光标开始就在输入框中,而且按下回车键将调用适当且可用的按钮。
这只是一个初级的例子,Tcl/Tk 有许多可以让间隔、字体、颜色和其他用户界面方面更具有吸引力的选项,这超出了本文中简单 UI 的示例。
运行这个应用,你可能会注意到这些部件看起来并不很精致或现代。这是因为我正在使用原始的经典部件集,它们让人回忆起 X Windows Motif 的时代。不过,还有一些默认的部件扩展,被称为主题部件,它们可以让你的应用程序有更现代、更精致的外观和感觉。
启动游戏!保存文件之后,在终端中运行它:
$ ./numgame.wish
在这种情况下,我无法给出控制台的输出,因此这里有一个动画 GIF 来展示如何玩这个游戏:
用 Wish 编写的猜数游戏
用 Wish 编写的猜数游戏
进一步了解 TclTcl 支持命名空间的概念,所以在这里使用的变量并不必须是全局的。你可以把绑定的部件变量组织进不同的命名空间。对于像这样的简单程序,可能并不太需要这么做。但对于更大规模的项目,你可能会考虑这种方法。
proc check_guess
函数体内有一行global
代码我之前没有解释。在 Tcl 中,所有变量都按值传递,函数体内引用的变量的范围是局部的。在这个情况下,我希望修改的是全局变量,而不是局部范围的版本。Tcl 提供了许多方法来引用变量,在执行堆栈的更高级别执行代码。在一些情况下,像这样的简单引用可能带来一些复杂性和错误,但是调用堆栈的操作非常有力,允许 Tcl 实现那些在其他语言中实现起来可能较为复杂的新的条件和循环结构。
最后,在这篇文章中,我没有提到几何管理器,它们用于以特定的顺序展示部件。只有被某种几何管理器管理的部件才能显示在屏幕上。grid 管理器相当简洁,它按照从左到右的方式放置部件。我使用了五个 grid 定义来创建了五行。另外还有两个几何管理器:place 和 pack。pack 管理器将部件围绕窗口边缘排列,而 place 管理器允许固定部件的位置。除这些几何管理器外,还有一些特殊的部件,如canvas
,text
和panedwindow
,它们可以容纳并管理其他部件。你可以在经典的 Tcl/Tk 参考指南,以及Tk 命令文档页上找到这些部件的全面描述。
Tcl 和 Tk 提供了一个简单有效的方法来构建图形用户界面和事件驱动应用程序。这个简单的猜数游戏只是你能用这些工具做到的事情的起点。通过继续学习和探索 Tcl 和 Tk,你可以打开构建强大且用户友好的应用程序的无数可能性。继续尝试,继续学习,看看你新习得的 Tcl 和 Tk 技能能带你到哪里。
标签:
探索Tcl Tk的基础构造,包括用户输入、输出、变量、条件评估、简单函数
四川新闻网-首屏新闻内江9月8日讯9月8日,威远美能页岩气新材料一体化
新华财经注意到,目前浦发银行已提名公司党委书记张为忠、赵万兵为公司
值得一提的是,受益于商业地产类消费基础设施REITs政策,2023年1-8月,
投资山西,央企多领域布局大项目,主流媒体,山西门户。山西新闻网是经国
南方财经9月8日电,北京市人民政府办公厅印发《北京市促进未来产业创新
,你们好,今天0471房产来聊聊一篇狍皮围子,狍皮围子简述的文章,网友
,你们好,今天0471房产来聊聊一篇非情深,非情深简述的文章,网友们对
武昌区杨园街道企业反诈宣传进影院营商环境”两手抓“、防非法治“两不
23重庆债41票面利率为2 7300%
蓝箭电子今日下跌1 49%,全天换手率49 05%,成交额13 71亿元,振幅9 49
2023年慕尼黑国际车展期间,全球豪华纯电高性能汽车品牌Polestar极星将
9月8日下午,在喜迎建校75周年,第39个教师节即将到来之际,吉林农业大
极目新闻记者卢成汉通讯员黄建兵9月7日晚,武汉新洲区城管执法局、长江
据蚂蚁国际事业群总裁杨鹏透露:“Alipay+搭建跨境支付的桥梁,通过这
大众网记者王焕焕通讯员徐慎鹏青岛报道近年来,青岛西海岸新区市政设施
保靖县中等职业技术学校模具制造技术专业介绍:模具制造技术专业培养目
近日,福建省人民政府发布一批人事任免,任命刘用通为福建省广播影视集
为进一步加强学生行为规范教育,培养学生良好的行为习惯和文明素养,9
什么决定交通事故精神赔偿额根据《最高人民法院关于审理人身损害赔偿案
2023年9月1日至5日,IFA2023(德国柏林国际电子消费品展览会)在德国柏
您好,来为大家解答以上问题。广西柳州门莫菁现状,柳州莫菁什么回事很
9月8日,由郑州市人民政府、郑州商品交易所(以下简称郑商所)、芝商所
受暴雨影响,港交所首次公开招股结算平台FINI第二次市场演习再次顺延,
9月8日盘中消息10点9分菲林格尔603226触及跌停板目前价格587下跌997其
企查查APP显示,库车市泰翰新能源科技有限责任公司成立,法定代表人为
解读中国投资热点城市①:广州南沙,南沙,厦门,投洽会,广州市,中国投资
昨日(9月7日),由静海区委、区政府主办的静海军民战洪图──海河“23
焰灵姬,是中国动画《天行九歌》系列中的原创女性角色,是赤眉龙蛇天泽
根据相关法规,退休是指劳动者达到法定退休年龄,或者因身体或工作条件
Copyright © 2015-2022 热讯服装网版权所有 备案号:豫ICP备20005723号-6 联系邮箱:29 59 11 57 8@qq.com