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 命令,它会自动启动事件循环你.
我正在编写一个基本脚本,它可以在 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 命令,它会自动启动事件循环你.