Tcl Tk窗口未出现

Tcl Tk窗口未出现,tcl,tk,Tcl,Tk,我正在写一个基本的脚本,在500x500窗口周围随机移动一个红方块。但是,当我运行代码时,该窗口不会出现,并且不会显示任何错误消息 我已经尝试使用wish和terminal来运行代码,但两者都不起作用 仅供参考:pass是我的无所事事功能 我的代码是: #!/usr/bin/tclsh proc pass {} {} proc rand { min max } { set maxFactor [expr [expr $max + 1] - $min] set value [e

我正在写一个基本的脚本,在500x500窗口周围随机移动一个红方块。但是,当我运行代码时,该窗口不会出现,并且不会显示任何错误消息

我已经尝试使用wish和terminal来运行代码,但两者都不起作用

仅供参考:
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中工作的唯一方式是通过稳定的事件流。按钮点击、滚动,甚至来自操作系统的重新绘制窗口的请求都是事件。如果无法处理这些事件,GUI将被冻结或从未出现

由于无限循环,这些事件永远不会被处理。因此,即使最初的“在屏幕上画你自己”事件也会被完全忽略

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

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

示例

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

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

proc move_label {} {
    set x [rand 0 500]
    set y [rand 0 500]
    place .l -x $x -y $y
}
接下来,创建一个调用此函数的函数,然后在之后使用
安排再次调用该函数:

proc animate {} {
    move_label
    after 1000 animate
}
最后,在创建标签后调用此函数一次,它将每秒运行一次,直到程序退出

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


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

GUI中任何操作的唯一方式是通过稳定的事件流。按钮点击、滚动,甚至来自操作系统的重新绘制窗口的请求都是事件。如果无法处理这些事件,GUI将被冻结或从未出现

由于无限循环,这些事件永远不会被处理。因此,即使最初的“在屏幕上画你自己”事件也会被完全忽略

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

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

示例

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

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

proc move_label {} {
    set x [rand 0 500]
    set y [rand 0 500]
    place .l -x $x -y $y
}
接下来,创建一个调用此函数的函数,然后在
之后使用
安排再次调用该函数:

proc animate {} {
    move_label
    after 1000 animate
}
最后,在创建标签后调用此函数一次,它将每秒运行一次,直到程序退出

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


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

您可以将
包要求tk
放在顶部,让
tclsh
wish
一样工作;建议这样做。这两天的主要区别是1)默认的
包需要Tk
和2)在Windows上如何将
wish
构建为GUI应用程序而不是控制台应用程序。您可以将
package require Tk
放在顶部,让
tclsh
wish
一样工作;建议这样做。这两天的主要区别是1)默认的
包需要Tk
和2)在Windows上如何将
wish
构建为GUI应用程序而不是控制台应用程序。