Tk window 没有出现

Tk window not appearing

我正在编写一个基本脚本,它可以在 500x500 window 周围随机方向移动一个红色方块。但是,当我 运行 代码时 window 没有出现,也没有显示错误消息。

我试过同时使用 wish 和终端来 运行 代码,但都不起作用。

仅供参考:pass 是我的无所事事功能

我的代码是:

#!/usr/bin/tclsh

proc pass {} {}

proc rand { min max } {
    set maxFactor [expr [expr $max + 1] - $min]
    set value [expr int([expr rand() * 100])]
    set value [expr [expr $value % $maxFactor] + $min]
return $value
}

package require Img

wm geometry . 500x500
wm title . "move"

. configure -background "#333"

set x "250"
set y "250"

image create photo img1 -file "square.png"
label .l -image img1
place .l -x $x -y $y


while {"3" eq "3"} {
    set command [rand 1 4]
    if {$command eq 1} {
        eval "if {$y ne 5} {\nincr y -5\nplace .l -x $x -y $y\n}"
    } elseif {$command eq 2} {
        eval "if {$y ne 475} {\nincr y 5\nplace .l -x $x -y $y\n}"
    } elseif {$command eq 3} {
        eval "if {$x ne 5} {\nincr x -5\nplace .l -x $x -y $y\n}"
    } elseif {$command eq 4} {
        eval "if {$x ne 475} {\nincr x 5\nplace .l -x $x -y $y\n}"
    }
}

任何东西在 GUI 中工作的唯一方法是通过稳定的事件流。按钮点击、滚动,甚至操作系统请求重绘 window 都是事件。如果无法处理这些事件,GUI 将被冻结或永远不会出现。

由于无限循环,这些事件永远不会被处理。因此,即使是最初的 "draw yourself on the screen" 事件也被完全忽略了。

基于事件的编程与编写非基于事件的编程不同。您不能只期望代码从上到下一次 运行 。相反,您必须设置 GUI 以正确生成和响应事件。

如果你想在随机方向移动正方形,正确的方法是创建一个移动它一次的函数,然后安排每隔一段时间调用该函数。您可以使用 after 命令执行最后一部分 —— 运行 在将来创建一个函数。这使您可以在事件队列中放置一个事件,该事件指示程序 运行 您的函数。

例子

为简化示例,以下代码只是将标签移动到随机位置,而不是使用原始代码的复杂逻辑。如果需要,您可以稍后修改该函数以使用现有逻辑。我想尽可能多地消除复杂性,以便您可以理解该技术。

首先从移动标签一次的函数开始:

proc move_label {} {
    set x [rand 0 500]
    set y [rand 0 500]
    place .l -x $x -y $y
}

接下来,创建一个调用这个函数的函数,然后使用after:

安排自己再次被调用
proc animate {} {
    move_label
    after 1000 animate
}

最后,在创建标签后调用此函数一次,它将每秒 运行 一次,直到程序退出。

label .l -image img1
animate

通过让 animate 函数调用 after 自身,您将得到一个永无止境的循环,运行 大约每秒一次。在循环迭代之间,tcl 可以自由处理允许 GUI 继续响应用户和 OS 事件的所有其他事件。

注意:您需要 运行 使用 wish 而不是 tclsh,因为 wish 包含 tk 命令,它会自动启动事件循环你.