跳转至内容

Tcl 编程/Tk

来自 Wikibooks,开放世界的开放书籍

Tk(工具包)是用于在 Macintosh、Unix/Linux 或 Windows 操作系统上设计图形用户界面 (GUI) 最流行的 Tcl 扩展。

只需少量努力,就可以组合出有用的

  • 窗口(表单,有些人称之为)由
  • 部件组成,这些部件由
  • 几何管理器管理。此外,您可以轻松定义
  • 鼠标或键盘事件的绑定以触发您想要的动作。

示例:计算器

[编辑 | 编辑源代码]

这是一个非常简单、完整的 Tcl/Tk 脚本,实现了计算器

package require Tk
pack [entry .e -textvar e -width 50]
bind .e <Return> {
   set e  [regsub { *=.*} $e ""] ;# remove evaluation (Chris)
   catch {expr [string map {/ *1./} $e]} res
   append e " = $res"
} 

它创建了一个名为 .e输入框部件,您可以在其中从键盘输入,并关联一个变量 e(它将反映输入框的内容),并使用 pack 管理它。

定义了一个绑定:如果键盘焦点在 .e 上,并且按下 <Return> 键,则

  • 变量 e 中的所有除法运算符 (/) 都会映射到 "*1./"(这强制进行浮点除法),
  • 将生成的字符串提供给 expr 以将其评估为算术/逻辑表达式
  • 由于用户输入中可能存在错误,因此 expr 调用被包装在 catch 中,该 catchexpr 的结果或发生的错误消息分配给变量 res
  • 最后一次评估的结果通过删除 = 后面的所有内容来清除
  • 最后,一个等号和 res 变量的值被 appende 中,使输入和结果立即在输入框中可见。

示例:一个微型 IRC 客户端

[编辑 | 编辑源代码]

与之前 Tcl 部分一样,这里再次提供了一个可运行的小脚本:一个 38 行代码的 IRC(互联网中继聊天)客户端,它具有 文本框输入框部件

package require Tk
set ::server irc.freenode.org
set ::chan   #tcl
set ::me     $tcl_platform(user)
text .t -height 30 -wrap word -font {Arial 9}
.t tag config bold   -font [linsert [.t cget -font] end bold]
.t tag config italic -font [linsert [.t cget -font] end italic]
.t tag config blue   -foreground blue
entry .cmd
pack .cmd -side bottom -fill x
pack .t -fill both -expand 1
bind .cmd <Return> post
proc recv {} {
    gets $::fd line
    if {[regexp {:([^!]*)![^ ].* +PRIVMSG ([^ :]+) +:(.*)} $line -> \
        nick target msg]} {
        set tag ""
        if [regexp {\001ACTION(.+)\001} $msg -> msg] {set tag italic}
        if [in {azbridge ijchain} $nick] {regexp {<([^>]+)>(.+)} $msg -> nick msg}
       .t insert end $nick\t bold $msg\n $tag
    } else {.t insert end $line\n italic}
    .t yview end
}
proc in {list element} {expr {[lsearch -exact $list $element]>=0}}
proc post {} {
    set msg [.cmd get]
    if [regexp {^/me (.+)} $msg -> action] {set msg "\001ACTION $action\001"}
    foreach line [split $msg \n] {send "PRIVMSG $::chan :$line"}
    .cmd delete 0 end
    set tag ""
    if [regexp {\001ACTION(.+)\001} $msg -> msg] {set tag italic}
    .t insert end $::me\t {bold blue} $msg\n [list blue $tag]
    .t yview end
}
proc send str {puts $::fd $str; flush $::fd}
set ::fd [socket $::server 6667]
send "NICK $::me"
send "USER $::me 0 * :PicoIRC user"
send "JOIN $::chan"
fileevent $::fd readable recv
bind . <Escape> {exec wish $argv0 &; exit}

最后一行是一个快速调试助手:如果您在编辑器中修改了脚本,保存到磁盘,然后在应用程序中按下 <Escape> 以重新启动它。

部件是 GUI 对象,当由几何管理器映射时,对应于屏幕上的一个矩形区域,具有不同的属性和功能。

部件使用路径名称命名,有点类似于文件系统路径名称,只是部件的分隔符是句点“.”。例如,.foo.barfoo 的子部件,而 foo 是“.”的子部件。父子关系通常发生在容器中,例如 顶级窗口、框架、画布、文本框。名称部分(即句点之间的部分)几乎可以是任何不包含“.”的字符串,或者不以大写字母开头(这是因为以大写字母开头的部件类名称具有特殊含义,它们表示类范围的选项)。

如果您有一个接受父部件 w 并添加子部件的过程,区分 w 是“.”还是其他部件可能很重要 - 因为您不能将子部件名称直接连接到“.” - 如果 $w == “.”,则 $w.kid 将生成无效名称。以下是如何避免这种情况

set w2 [expr {$w eq "."? "": $w}]
button $w2.$kid ...

部件由以其类命名的命令创建,然后获取路径名称(要求父部件在那时必须存在)和任意数量的-key value选项,这些选项构成初始配置,例如

button .b -text "Hello!" -command {do something}

创建后,与部件的通信通过对应于其名称的创建命令进行。例如,可以查询配置选项

set text [.b cget -text]

或更改

.b configure -text Goodbye! -background red

一些“方法”,如 cget、configure 对所有部件类都是通用的,其他方法则特定于一个或几个部件类。例如,文本框输入框都接受 insert 方法。有关所有详细信息,请参阅手册页。

部件仅在被提供给几何管理器后才会显示在屏幕上(请参阅下面的更多信息)。示例

text .t -wrap word
pack .t -fill both -expand 1

由于部件创建命令返回路径名称,因此这两个步骤也可以嵌套,例如

pack [text .t -wrap word] -fill both -expand 1

destroy 命令删除一个部件及其所有子部件(如果存在)

destroy .b

以下子章节描述了 Tk 中可用的部件。


带有文本和/或图像,单击时调用可配置的命令。示例

button .b -text Hello! -command {puts "hello, world"}

用于线条、矩形、多边形、椭圆和文本项以及位图和照片图像以及整个嵌入式窗口的可滚动图形表面。例如,请参阅下面的“微型绘图程序”。示例

pack [canvas .c -background white]
.c create line 50 50 100 100 150 50 -fill red -width 3
.c create text 100 50 -text Example

平移画布(在窗口内使用鼠标中键按住的情况下滚动它)通过继承文本部件绑定

 bind .c <2> [bind Text <2>]
 bind .c <B2-Motion> [bind Text <B2-Motion>]

输入框

[编辑 | 编辑源代码]

单行可编辑文本字段,水平可滚动(请参阅上面的示例)。您可以指定验证函数来约束输入的内容。示例

entry .e -width 20 -textvariable myVar
set myVar "this text appears in the entry"


多个部件的容器,通常与 pack 一起使用,或用于包装“Megawidgets”

用于文本显示的一行或多行字段,可以绑定到文本变量以在该变量更改时更新。换行符由要显示的文本中的 \n 指定。

标签框架

[编辑 | 编辑源代码]

类似于框架的容器,周围装饰有细矩形,左上角位置有一个标签。示例(一个微型无线电波段选择器)

pack [labelframe .lf -text Band]
pack [radiobutton .lf.am -text AM -variable band -value AM]
pack [radiobutton .lf.fm -text FM -variable band -value FM]
set band AM

列表框

[编辑 | 编辑源代码]

列表的多行显示,可滚动。可以使用鼠标选择单个或多个项目。

要向GUI应用程序添加菜单,需要分三步操作

  • 创建顶层水平菜单(只需一次)
. configure -menu [menu .m]
  • 对于顶层菜单中的每个项目,创建一个级联子菜单,例如:
.m add cascade -label File -menu [menu .m.mFile]
  • 对于子菜单中的每个条目,像这样添加它:
.m.mFile add command -label Open -command {openFile ...}
.m.mFile add separator

由于这些命令有点冗长,可以将它们包装到一个小的辅助函数中

proc m+ {head name {cmd ""}} {
   if {![winfo exists .m.m$head]} {
        .m add cascade -label $head -menu [menu .m.m$head -tearoff 0]
   }
   if [regexp ^-+$ $name] {
           .m.m$head add separator
   } else {.m.m$head add command -label $name -comm $cmd}
}

演示示例 - 现在菜单项可以用更清晰的方式创建了

. configure -menu [menu .m]
m+ File Open {.t insert end "opened\n"}
m+ File Save {.t insert end "saved\n"}
m+ File -----
m+ File Exit exit
m+ Edit Cut ...
pack [text .t -wrap word] -fill both -expand 1

单选按钮

[编辑 | 编辑源代码]

带选择字段的按钮,可以处于打开或关闭状态,并带有一个标签。用鼠标点击选择字段会更改关联的全局变量的值。通常,多个单选按钮会绑定到同一个变量。例如,请参见上面的标签框架

滚动条

[编辑 | 编辑源代码]

水平或垂直滚动条(默认情况下为垂直,对于水平,指定:-orientation horizontal,或者如果您喜欢简短的写法,则使用 -ori hori)可以绑定到画布、输入框、列表框或文本小部件。滚动条与其滚动小部件之间的交互通过回调函数实现,其中一个通知另一个。

  • 滚动条到小部件:xviewyview 方法
  • 小部件到滚动条:set 方法

当回调函数被调用时,这些方法的参数将被自动添加。

例如,以下是将文本小部件与垂直滚动条连接的方法:

pack [scrollbar .y -command ".t yview"] -side right -fill y
pack [text .t -wrap word -yscrollc ".y set"] \
     -side right -fill both -expand 1

对于大多数小部件,滚动条会自动调整到小部件的内容。对于画布小部件,您需要在添加新项目后更新滚动区域。最简单的方法如下:

$canvas configure -scrollregion [$canvas bbox all]

可滚动的可编辑多行文本,具有许多格式选项。还可以包含图像和嵌入式小部件。默认换行设置是“none”,因此您可能需要水平滚动条才能查看所有长行。在许多情况下,将文本小部件配置为-wrap word 会更友好 - 这样您最多只需要一个垂直滚动条。

文本小部件中的位置指定为行.列,其中行从1开始,列从0开始,因此1.0是文本小部件中的第一个字符。如何删除所有内容的示例:

$t delete 1.0 end

要突出显示部分内容,可以定义标签并将它们分配给子序列

$t tag configure ul -underline 1
$t insert end "The next word is " {} underlined ul ", the rest is not."

顶层窗口

[编辑 | 编辑源代码]

独立的框架窗口,主要带有窗口管理器提供的装饰(标题栏、按钮)。当您启动Tk时,会收到一个名为“.”(一个点)的初始空顶层窗口。如果您想要更多顶层窗口,可以像这样创建它们:

toplevel .mySecondWindow

这些顶层窗口在逻辑上是“.”的子窗口。要为顶层窗口分配一个好的标题,请使用:

wm title $toplevel "This is the title"

您还可以使用以下方法控制顶层窗口的几何形状(大小和位置):

wm geometry $toplevel ${width}x$height+$x+$y

几何管理器

[编辑 | 编辑源代码]

几何管理器的目的是计算小部件所需的高度、宽度和位置,并将其映射到屏幕上。除了gridpackplace 之外,canvastext 小部件也可以管理嵌入式小部件。

对几何管理器的调用总是以管理器的名称开头,然后(大多)是一个或多个小部件名称,然后是任意数量的-name value选项

网格布局

[编辑 | 编辑源代码]

此几何管理器最适合用于由行和列组成的表格窗口布局。例如,要将三个小部件放在水平行中:

grid .1 .2 .3 -sticky news

-sticky 选项指示小部件应粘贴到其框的哪一边,以罗盘方向表示;“news”表示北-东-西-南”,即所有四面。

以下是在网格中显示表格(列表的列表)的最小解决方案:

package require Tk
proc table {w content args} {
    frame $w -bg black
    set r 0
    foreach row $content {
        set fields {}
        set c 0
        foreach col $row {
            lappend fields [label $w.$r/$c -text $col]
            incr c
        }
        eval grid $fields -sticky news -padx 1 -pady 1
        incr r
    }
    set w
}
#--- Test:
table .t {
   {Row Head1 Head2}
   {1   foo   42}
   {2   bar   1234}
   {3   grill testing}
}
pack .t
#--- Changing the contents, given row and column number:
after 2000 .t.3/2 config -text Coucou

填充布局

[编辑 | 编辑源代码]

这曾经是主力管理器,但在最近几年,它的流行度不如网格布局。无论如何,它仍然适用于您只需要在一个方向(水平或垂直)上对齐小部件的情况。对于更复杂的布局,过去常常插入中间框架,但网格布局使这些工作变得更容易。示例:

pack .x -fill both -expand 1 -side left

定位布局

[编辑 | 编辑源代码]

此几何管理器不常使用,主要用于特殊应用程序,例如当您想要突出显示选项卡笔记本的当前选项卡时。它允许以像素为单位精确放置小部件,但在响应顶层窗口或内部小部件的大小调整方面不太动态。

对话框

[编辑 | 编辑源代码]

对话框是用于显示消息或询问问题的顶层窗口。您不必为它们分配小部件路径名称。只需像调用函数一样调用它们并评估结果(如果对话框被取消,通常为“”)。

tk_getOpenFile

[编辑 | 编辑源代码]

文件选择器对话框(仅限于现有文件)。返回带有路径名称的选择文件,如果取消则返回“” 。

tk_getSaveFile

[编辑 | 编辑源代码]

文件选择器对话框,它也允许指定不存在的文件。返回带有路径名称的选择文件,如果取消则返回“” 。

tk_messageBox

[编辑 | 编辑源代码]

一个简单的对话框,显示一个字符串,可以用“确定”按钮关闭。示例:

tk_messageBox -message "hello, world!"

tk_chooseColor

[编辑 | 编辑源代码]

显示颜色选择对话框。返回值是根据Tcl对这类信息的理解,以某种表示形式呈现的选择颜色;在Microsoft Windows系统上,这可能是一个“#RRGGBB”格式的十六进制字符串。在终止该过程时,将传递空字符串。可以通过“-initialcolor”选项配置对话框以预选特定的默认颜色,通过“-parent”配置到父小部件的从属关系,以及通过“-title”配置标题。

 tk_chooseColor -initialcolor #FF0000 -parent . -title "What tincture do you wish?"

自定义对话框

[编辑 | 编辑源代码]

除了Tk自带的预制对话框外,构建自定义对话框也不太难。作为一个非常简单的例子,这里有一个“值对话框”,提示用户输入一个值:

proc value_dialog {string} {
   set w [toplevel .[clock seconds]]
   wm resizable $w 0 0
   wm title $w "Value request"
   label  $w.l -text $string
   entry  $w.e -textvar $w -bg white
   bind $w.e <Return> {set done 1}
   button $w.ok     -text OK     -command {set done 1}
   button $w.c      -text Clear  -command "set $w {}"
   button $w.cancel -text Cancel -command "set $w {}; set done 1"
   grid $w.l  -    -        -sticky news
   grid $w.e  -    -        -sticky news
   grid $w.ok $w.c $w.cancel
   vwait done
   destroy $w
   set ::$w
}

测试

set test [value_dialog "Give me a value please:"]
puts test:$test
pack [ label .l -text "Value: '$test' " ]

对于更复杂的示例,这里有一个记录编辑器对话框(多个字段,每个字段都有一个标签和输入框(或用于多行输入的文本)):

proc editRecord {title headers fields} {
    set oldfocus [focus]
    set w [toplevel .[clock clicks]]
    wm resizable $w 1 0
    wm title $w $title
    set n 0
    foreach h $headers f $fields {
        if ![regexp {(.+)([=+])} $h -> hdr type] {set hdr $h; set type ""}
        label $w.h$n -text $hdr -anchor ne
        switch -- $type {
            = {label $w.e$n -width [string length $f] -text $f -anchor w -bg white}
            + {[text $w.e$n -width 20 -height 6] insert end $f}
            default {[entry $w.e$n -width [string length $f]] insert end $f}
        }
        grid $w.h$n $w.e$n -sticky news
        incr n
    }
    button $w.ok -text OK -width 5 -command [list set $w 1]
    button $w.cancel -text Cancel -command [list set $w 0]
    grid $w.ok $w.cancel -pady 5
    grid columnconfigure $w 1 -weight 1
    vwait ::$w
    if [set ::$w] { #-- collect the current entry contents
        set n 0
        foreach h $headers f $fields {
            regexp {([^=+].+)([=+]?)} $h -> hdr type
            switch -- $type {
                "" {lappend res [$w.e$n get]}
                =  {lappend res [$w.e$n cget -text]}
                +  {lappend res [$w.e$n get 1.0 end]}
            }
            incr n
        }
    } else {set res {}}
    destroy $w
    unset ::$w ;#-- clean up the vwait variable
    focus $oldfocus
    return $res
}

快速测试

editRecord Test {foo= bar grill+} {one two three}

轻松创建巨型小部件

[编辑 | 编辑源代码]

术语“巨型小部件”常用于复合小部件,它们本身包含其他小部件,尽管它们的数量几乎不会达到一百万(前缀Mega-所暗示的),子小部件的数量通常不会超过十个。

要创建巨型小部件,需要一个与Tk小部件创建命令具有相同签名的过程。当此过程被调用时,它将创建一个以小部件命名的另一个过程,并将方法分派到特定的处理程序或Tk创建的通用小部件命令。

一个小笔记本

[编辑 | 编辑源代码]

普通的 Tk 没有包含“笔记本”控件,它没有顶部带标签的选项卡,可以切换显示不同的“页面”,但是很容易自己做一个。这个例子演示了如何用框架中的按钮实现选项卡,以及如何“重载”以框架命名的原始 Tk 命令,使其能够接收额外的添加切换方法。

proc notebook {w args} {
   frame $w
   pack [frame $w.top] -side top -fill x -anchor w
   rename $w _$w
   proc $w {cmd args} { #-- overloaded frame command
       set w [lindex [info level 0] 0]
       switch -- $cmd {
           add     {notebook'add   $w $args}
           raise   {notebook'raise $w $args}
           default {eval [linsert $args 0 _$w $cmd]}
       }
   }
   return $w
}
proc notebook'add {w title} {
   set btn [button $w.top.b$title -text $title -command [list $w raise $title]]
   pack $btn -side left -ipadx 5
   set f [frame $w.f$title -relief raised -borderwidth 2]
   pack $f -fill both -expand 1
   $btn invoke
   bind $btn <3> "destroy {$btn}; destroy {$f}" ;# (1)
   return $f
}
proc notebook'raise {w title} {
   foreach i [winfo children $w.top] {$i config -borderwidth 0}
   $w.top.b$title config -borderwidth 1
   set frame $w.f$title
   foreach i [winfo children $w] {
       if {![string match *top $i] && $i ne $frame} {pack forget $i}
   }
   pack $frame -fill both -expand 1
}

测试和演示代码

package require Tk
pack [notebook .n] -fill both -expand 1
set p1 [.n add Text]
pack   [text $p1.t -wrap word] -fill both -expand 1
set p2 [.n add Canvas]
pack   [canvas $p2.c -bg yellow] -fill both -expand 1
set p3 [.n add Options]
pack   [button $p3.1 -text Console -command {console show}]
.n raise Text
wm geometry . 400x300

绑定事件

[编辑 | 编辑源代码]

Tcl/Tk 中的事件包括用户执行的操作,例如按下按键或单击鼠标。要对鼠标和键盘活动做出反应,可以使用 bind 命令。如计算器示例所示。

 pack [entry .e -textvar e -width 50]
 bind .e <Return> {

bind 关键字作用于 .e 并将事件与 <return> 事件相关联。下面的括号表示一组过程的开始,当事件发生时执行这些过程。

BWidget 是一个用纯 Tcl 编写的 Tk 扩展(因此它甚至可以在 Windows Mobile 驱动的手机上运行)。它提供了巨型控件(所有类名都以大写字母开头),例如

  • 组合框
  • 笔记本
  • 树形控件

在 Windows/CE 下的 PocketPC 上,笔记本和树形控件的屏幕截图

树形控件示例

[编辑 | 编辑源代码]

这是一个树形控件的“Hello World”示例(这是一个完整的脚本)。根节点始终称为root,对于其他节点,您需要自己命名。

package require BWidget
pack [Tree .t]
.t insert end root n1  -text hello
.t insert end root n2  -text world
.t insert end n2   n21 -text (fr:monde)
.t insert end n2   n22 -text (de:Welt)

著名的打字测试句子表示为语法树

package require BWidget
pack [Tree .t -height 16] -fill both -expand 1
foreach {from to text} {
   root S S
   S   np1  NP
   S   vp   VP
   np1 det1 Det:The
   np1 ap1  AP
   ap1 adj1 Adj:quick
   ap1 adj2 Adj:brown
   ap1 n1   N:fox
   vp  v    V:jumps
   vp  pp   PP
   pp  prep Prep:over
   pp  np2  NP
   np2 det2 Det:the
   np2 ap2  AP
   ap2 adj3 Adj:lazy
   ap2 n2   N:dog
   
} {.t insert end $from $to -text $text}
.t opentree S

Tk 资源

[编辑 | 编辑源代码]

Tk 中的颜色可以通过三种方式指定

  • 符号名称,例如:红色 绿色 蓝色 黄色 品红 青色
  • 以 # 开头的十六进制字符串:#RGB、#RRGGBB、#RRRRGGGGBBBB
  • 三个非负整数的列表

最后一种形式仅由命令返回。要为命令指定颜色,您需要将其格式化为十六进制。例如,白色可以描述为 #FFFFFF。

将符号名称转换为其 RGB 分量

winfo rgb . $colorname

以下是定义的颜色名称列表(来自 X11 的 rgb.txt)

set COLORS { snow {ghost white} {white smoke} gainsboro {floral white}
   {old lace} linen {antique white} {papaya whip} {blanched almond}
   bisque {peach puff} {navajo white} moccasin cornsilk ivory {lemon
   chiffon} seashell honeydew {mint cream} azure {alice blue}
   lavender {lavender blush} {misty rose} white black {dark slate
   gray} {dim gray} {slate gray} {light slate gray} gray {light grey}
   {midnight blue} navy {cornflower blue} {dark slate blue} {slate
   blue} {medium slate blue} {light slate blue} {medium blue} {royal
   blue} blue {dodger blue} {deep sky blue} {sky blue} {light sky
   blue} {steel blue} {light steel blue} {light blue} {powder blue}
   {pale turquoise} {dark turquoise} {medium turquoise} turquoise
   cyan {light cyan} {cadet blue} {medium aquamarine} aquamarine
   {dark green} {dark olive green} {dark sea green} {sea green}
   {medium sea green} {light sea green} {pale green} {spring green}
   {lawn green} green chartreuse {medium spring green} {green yellow}
   {lime green} {yellow green} {forest green} {olive drab} {dark
   khaki} khaki {pale goldenrod} {light goldenrod yellow} {light
   yellow} yellow gold {light goldenrod} goldenrod {dark goldenrod}
   {rosy brown} {indian red} {saddle brown} sienna peru burlywood
   beige wheat {sandy brown} tan chocolate firebrick brown {dark
   salmon} salmon {light salmon} orange {dark orange} coral {light
   coral} tomato {orange red} red {hot pink} {deep pink} pink {light
   pink} {pale violet red} maroon {medium violet red} {violet red}
   magenta violet plum orchid {medium orchid} {dark orchid} {dark
   violet} {blue violet} purple {medium purple} thistle snow2 snow3
   snow4 seashell2 seashell3 seashell4 AntiqueWhite1 AntiqueWhite2
   AntiqueWhite3 AntiqueWhite4 bisque2 bisque3 bisque4 PeachPuff2
   PeachPuff3 PeachPuff4 NavajoWhite2 NavajoWhite3 NavajoWhite4
   LemonChiffon2 LemonChiffon3 LemonChiffon4 cornsilk2 cornsilk3
   cornsilk4 ivory2 ivory3 ivory4 honeydew2 honeydew3 honeydew4
   LavenderBlush2 LavenderBlush3 LavenderBlush4 MistyRose2 MistyRose3
   MistyRose4 azure2 azure3 azure4 SlateBlue1 SlateBlue2 SlateBlue3
   SlateBlue4 RoyalBlue1 RoyalBlue2 RoyalBlue3 RoyalBlue4 blue2 blue4
   DodgerBlue2 DodgerBlue3 DodgerBlue4 SteelBlue1 SteelBlue2
   SteelBlue3 SteelBlue4 DeepSkyBlue2 DeepSkyBlue3 DeepSkyBlue4
   SkyBlue1 SkyBlue2 SkyBlue3 SkyBlue4 LightSkyBlue1 LightSkyBlue2
   LightSkyBlue3 LightSkyBlue4 SlateGray1 SlateGray2 SlateGray3
   SlateGray4 LightSteelBlue1 LightSteelBlue2 LightSteelBlue3
   LightSteelBlue4 LightBlue1 LightBlue2 LightBlue3 LightBlue4
   LightCyan2 LightCyan3 LightCyan4 PaleTurquoise1 PaleTurquoise2
   PaleTurquoise3 PaleTurquoise4 CadetBlue1 CadetBlue2 CadetBlue3
   CadetBlue4 turquoise1 turquoise2 turquoise3 turquoise4 cyan2 cyan3
   cyan4 DarkSlateGray1 DarkSlateGray2 DarkSlateGray3 DarkSlateGray4
   aquamarine2 aquamarine4 DarkSeaGreen1 DarkSeaGreen2 DarkSeaGreen3
   DarkSeaGreen4 SeaGreen1 SeaGreen2 SeaGreen3 PaleGreen1 PaleGreen2
   PaleGreen3 PaleGreen4 SpringGreen2 SpringGreen3 SpringGreen4
   green2 green3 green4 chartreuse2 chartreuse3 chartreuse4
   OliveDrab1 OliveDrab2 OliveDrab4 DarkOliveGreen1 DarkOliveGreen2
   DarkOliveGreen3 DarkOliveGreen4 khaki1 khaki2 khaki3 khaki4
   LightGoldenrod1 LightGoldenrod2 LightGoldenrod3 LightGoldenrod4
   LightYellow2 LightYellow3 LightYellow4 yellow2 yellow3 yellow4
   gold2 gold3 gold4 goldenrod1 goldenrod2 goldenrod3 goldenrod4
   DarkGoldenrod1 DarkGoldenrod2 DarkGoldenrod3 DarkGoldenrod4
   RosyBrown1 RosyBrown2 RosyBrown3 RosyBrown4 IndianRed1 IndianRed2
   IndianRed3 IndianRed4 sienna1 sienna2 sienna3 sienna4 burlywood1
   burlywood2 burlywood3 burlywood4 wheat1 wheat2 wheat3 wheat4 tan1
   tan2 tan4 chocolate1 chocolate2 chocolate3 firebrick1 firebrick2
   firebrick3 firebrick4 brown1 brown2 brown3 brown4 salmon1 salmon2
   salmon3 salmon4 LightSalmon2 LightSalmon3 LightSalmon4 orange2
   orange3 orange4 DarkOrange1 DarkOrange2 DarkOrange3 DarkOrange4
   coral1 coral2 coral3 coral4 tomato2 tomato3 tomato4 OrangeRed2
   OrangeRed3 OrangeRed4 red2 red3 red4 DeepPink2 DeepPink3 DeepPink4
   HotPink1 HotPink2 HotPink3 HotPink4 pink1 pink2 pink3 pink4
   LightPink1 LightPink2 LightPink3 LightPink4 PaleVioletRed1
   PaleVioletRed2 PaleVioletRed3 PaleVioletRed4 maroon1 maroon2
   maroon3 maroon4 VioletRed1 VioletRed2 VioletRed3 VioletRed4
   magenta2 magenta3 magenta4 orchid1 orchid2 orchid3 orchid4 plum1
   plum2 plum3 plum4 MediumOrchid1 MediumOrchid2 MediumOrchid3
   MediumOrchid4 DarkOrchid1 DarkOrchid2 DarkOrchid3 DarkOrchid4
   purple1 purple2 purple3 purple4 MediumPurple1 MediumPurple2
   MediumPurple3 MediumPurple4 thistle1 thistle2 thistle3 thistle4
   gray1 gray2 gray3 gray4 gray5 gray6 gray7 gray8 gray9 gray10
   gray11 gray12 gray13 gray14 gray15 gray16 gray17 gray18 gray19
   gray20 gray21 gray22 gray23 gray24 gray25 gray26 gray27 gray28
   gray29 gray30 gray31 gray32 gray33 gray34 gray35 gray36 gray37
   gray38 gray39 gray40 gray42 gray43 gray44 gray45 gray46 gray47
   gray48 gray49 gray50 gray51 gray52 gray53 gray54 gray55 gray56
   gray57 gray58 gray59 gray60 gray61 gray62 gray63 gray64 gray65
   gray66 gray67 gray68 gray69 gray70 gray71 gray72 gray73 gray74
   gray75 gray76 gray77 gray78 gray79 gray80 gray81 gray82 gray83
   gray84 gray85 gray86 gray87 gray88 gray89 gray90 gray91 gray92
   gray93 gray94 gray95 gray97 gray98 gray99
}

此外,以下在 Windows 上定义

set WINDOWSCOLORS {
   SystemButtonFace SystemButtonText SystemDisabledText SystemHighlight
   SystemHightlightText SystemMenu SystemMenuText SystemScrollbar
   SystemWindow SystemWindowFrame SystemWindowText
}

对于每个控件,您可以指定鼠标悬停在其上时光标的外观。以下是定义的光标名称列表

set cursors {
   X_cursor arrow based_arrow_down based_arrow_up boat bogosity
   bottom_left_corner bottom_right_corner bottom_side bottom_tee
   box_spiral center_ptr circle clock coffee_mug cross cross_reverse
   crosshair diamond_cross dot dotbox double_arrow draft_large draft_small
   draped_box exchange fleur gobbler gumby hand1 hand2 heart icon
   iron_cross left_ptr left_side left_tee leftbutton ll_angle lr_angle
   man middlebutton mouse pencil pirate plus question_arrow right_ptr
   right_side right_tee rightbutton rtl_logo sailboat sb_down_arrow
   sb_h_double_arrow sb_left_arrow sb_right_arrow sb_up_arrow
   sb_v_double_arrow shuttle sizing spider spraycan star target tcross
   top_left_arrow top_left_corner top_right_corner top_side top_tee 
   trek ul_angle umbrella ur_angle watch xterm
}

一个小工具,它显示光标名称,并在鼠标悬停时显示每个光标的形状。

set ncols 4
for {set i 0} {$i<$ncols} {incr i} {
   lappend cols col$i
}
set nmax [expr {int([llength $cursors]*1./$ncols)}]
foreach col $cols {
   set $col [lrange $cursors 0 $nmax]
   set cursors [lrange $cursors [expr $nmax+1] end]
}
label .top -text "Move the cursor over a name to see how it looks" \
   -relief ridge
grid .top -columnspan $ncols -sticky news -ipady 2
for {set i 0} {$i<[llength $col0]} {incr i} {
   set row {}
   foreach col $cols {
       set name [lindex [set $col] $i]
       if {$name eq ""} break
       lappend row .l$name
       label .l$name -text $name -anchor w
       bind .l$name <Enter> [list %W config -cursor $name]
   }
   eval grid $row -sticky we
}

字体由窗口系统提供。哪些字体可用取决于本地安装。使用以下命令查找可用的字体:

font families

字体的典型描述最多包含三个元素的列表

family size ?style?

示例

set f {{Bitstream Cyberbit} 10 bold}

字体系列是一个名称,例如 Courier、Helvetica、Times 等。最好选择字体系列提供的名称之一,尽管可能存在一些映射,例如“Helvetica” -> “Arial”。

大小是以磅为单位(印刷工的磅是 1/72 英寸)如果为正数,或以像素为单位如果为负数。普通显示字体的大小通常为 9 或 10。

样式可以是零个或多个粗体、斜体、下划线等列表。

图像:照片和位图

Tk 允许对图像进行简单但功能强大的操作。这些图像分为两种:位图和照片。位图的功能相当有限,它们可以用 XBM 格式指定,并以可配置的颜色呈现。

照片的可能性要多得多 - 您可以使用不同的文件格式加载和保存它们(Tk 本身支持 PPM 和 GIF - 对于其他格式,请使用 Img 扩展),使用许多选项复制它们,例如缩放/二次采样或镜像,以及获取或设置单个像素的颜色。

设置还可以一次性处理矩形区域,以下示例演示了如何创建一个三色旗的照片图像(三个等间距的垂直条带 - 如法国、意大利、比利时、爱尔兰和许多其他国家)。默认值为法国。您可以指定宽度,高度将是宽度的 2/3。该过程返回图像名称 - 只要保存为 -format GIF 格式即可。

proc tricolore {w {colors {blue white red}}} {
   set im [image create photo]
   set fromx 0
   set dx [expr $w/3]
   set tox $dx
   set toy [expr $w*2/3]
   foreach color $colors {
       $im put $color -to $fromx 0 $tox $toy
       incr fromx $dx; incr tox $dx
   }
   set im
}
# Test - display flag on canvas:
pack [canvas .c -width 200 -height 200 -background grey]
.c create image 100 100 -image [tricolore 150]
# Test - save image of flag to file:
[tricolore 300] write tric.gif -format gif

调试 Tk 程序

[编辑 | 编辑源代码]

正在开发的 Tk 程序可以通过添加此类绑定来快速调试

bind . <F1> {console show}

这仅适用于 Windows 和 Macintosh(OS-X 之前版本),并在其中您可以与 Tcl 解释器交互,检查或修改全局变量,配置控件等的控制台中弹出一个控制台。

bind . <Escape> {eval [list exec wish $argv0] $argv &; exit}

这将启动当前程序的新实例(假设您编辑了源文件并将其保存到磁盘),然后终止当前实例。

对于简短的调试输出,还可以使用窗口的标题栏。例如,要显示鼠标移动时的当前鼠标坐标

bind . <Motion> {wm title . %X/%Y}

其他语言

[编辑 | 编辑源代码]

其他编程语言有与 Tcl/Tk 接口并使用它的模块

  • 在 R(编程语言)中,有一个 tcltk 库,使用命令library(tcltk)调用。
  • 在 Python 中,有一个 tkinter 模块,使用import tkinterfrom tkinter import *调用。
  • Common Lisp 可以通过几个外部可用的库与 Tcl/Tk 通信,包括CL-TKLTK
华夏公益教科书