我正在尝试使用tcl/tk
canvas实用工具在文件中绘制实时更改。我编写了一个简单的代码来查找文件中的差异并使用.c create line $oldx $oldy $newx $newy
命令对其进行绘制。
我的代码有一个while循环,可以继续检查文件中的更改。当我注释掉while循环时,绘图画布可以很好地打开,但是当我取消注释while循环时,绘图画布根本不会打开。
请提出修改建议,代码:
#!/usr/bin/wish
#PROGRAM 2 : Print something when a file is changed
#
#package require Tk
#graph prep
set width 100
set height 100
canvas .c -width $width -height $height -background white
pack .c
#bind .c <Configure> {
# bind .c <Configure> {}
# .c xview scroll 0 unit
# set t 0
#}
#set t 0
#.c create line $t 239 [expr $t + 5] 239 -fill gray
.c create line 0 12 1 13
#Initial reading
set filename "data.txt"
#puts $filename
if [file exists $filename] {
#puts "file exits!"
set accessTime [file mtime $filename]
#puts $accessTime
}
#opening file
set a [open $filename]
set lines [split [read -nonewline $a] "\n"]
close $a; # Saves a few bytes :-)
#puts [llength $lines]
#printing file
set oldx 0
set oldy [lindex $lines 0]
for {set i 1} {$i < [llength $lines]} {incr i} {
#puts "$i : [lindex $lines $i]"
set newx $i
set newy [lindex $lines $i]
.c create line $oldx $oldy $newx $newy
set oldx $newx
set oldy $newy
}
## after 10000
## #looping to detect change
while 1 {
if [file exists $filename] {
after 1000
# check if new access time
set nAccessTime [file mtime $filename]
if {$accessTime != $nAccessTime} {
#puts $nAccessTime
#puts "found new"
#update access time
set accessTime $nAccessTime
#read new lines
set a [open $filename]
set lines [split [read -nonewline $a] "\n"]
close $a; # Saves a few bytes :-)
#puts [llength $lines]
for {} {$i < [llength $lines]} {incr i} {
#puts "$i : [lindex $lines $i]"
set newx $i
set newy [lindex $lines $i]
.c create line $oldx $oldy $newx $newy
set oldx $newx
set oldy $newy
}
}
}
}
答案 0 :(得分:3)
这是在Tk中进行时间驱动的动态更新的经典问题(动画具有相同的问题)。问题在于,Tk仅在事件循环为 idle时重绘自身; 将实际的绘制活动推迟到发生为止,从而允许将多个状态更改分组为一个重绘(极大地提高了实际效率)。在大多数情况下,这是透明发生的,但是当您遇到了如您所写的驱动循环时,根本就不会发生任何更新。
解决此问题的快速方法是更改:
after 1000
收件人:
after 1000 {set update_ready yes}
vwait update_ready
在暂停期间运行事件循环,而不是完全停止该过程。另一种方法是改为将其更改为:
update
after 1000
但这是次等的,因为这意味着应用程序在等待期间无响应。
更好的是是重写代码,以便它处理计时器回调中的更改。这对您的代码来说是相当大的手术……除非您拥有Tcl 8.6,否则您可以使用协程轻松完成此操作:
package require Tcl 8.6; # <<<< GOOD STYLE
package require Tk; # <<<< GOOD STYLE
set width 100
set height 100
canvas .c -width $width -height $height -background white
pack .c
.c create line 0 12 1 13
#Initial reading
set filename "data.txt"
#puts $filename
if [file exists $filename] {
#puts "file exits!"
set accessTime [file mtime $filename]
#puts $accessTime
}
#opening file
set a [open $filename]
set lines [split [read -nonewline $a] "\n"]
close $a; # Saves a few bytes :-)
#puts [llength $lines]
#printing file
set oldx 0
set oldy [lindex $lines 0]
for {set i 1} {$i < [llength $lines]} {incr i} {
#puts "$i : [lindex $lines $i]"
set newx $i
set newy [lindex $lines $i]
.c create line $oldx $oldy $newx $newy
set oldx $newx
set oldy $newy
}
## #looping to detect change
coroutine mainloop apply {{} { # <<< CHANGED LINE
global i filename accessTime oldx oldy
while 1 {
after 1000 [info coroutine]; # <<< CHANGED LINE
yield; # <<< CHANGED LINE
if {[file exists $filename]} {
# check if new access time
set nAccessTime [file mtime $filename]
if {$accessTime != $nAccessTime} {
#puts $nAccessTime
#puts "found new"
#update access time
set accessTime $nAccessTime
#read new lines
set a [open $filename]
set lines [split [read -nonewline $a] "\n"]
close $a; # Saves a few bytes :-)
#puts [llength $lines]
for {} {$i < [llength $lines]} {incr i} {
#puts "$i : [lindex $lines $i]"
set newx $i
set newy [lindex $lines $i]
.c create line $oldx $oldy $newx $newy
set oldx $newx
set oldy $newy
}
}
}
}
}}
您可能还希望在检查文件是否存在之前有一定的延迟,以使不存在的文件不会导致您破坏操作系统。