我对tcl很满意,但是对tk新手很满意。 我想在一个窗口上显示一些文本,经过几次搜索,我在这里找到了一个对我来说很好的例子。 我的问题是显示器不是实时显示,而是仅在程序结束时显示。 以下是我的计划的主要内容。
Main_program.tcl
#!/bin/sh
# -*- tcl -*-
# The next line is executed by /bin/sh, but not tcl \
exec /usr/local/Cellar/tcl-tk/bin/tclsh "$0" "$@"
set DEBUG 1
source ./GUI_mgt.tcl
source ./utils.tcl
for {set i 0} {$i<500} {incr i} {
after 10
debug_puts $i
}
utils.tcl
proc debug_puts {message} {
if {$::DEBUG} { writeToLog $message }
}
GUI_mgt.tcl
package require Tk
grid [text .log -state disabled -width 80 -height 24 -wrap none]
proc writeToLog {msg} {
set numlines [lindex [split [.log index "end - 1 line"] "."] 0]
.log configure -state normal
if {$numlines==24} {.log delete 1.0 2.0}
if {[.log index "end-1c"]!="1.0"} {.log insert end "\n"}
.log insert end "$msg"
.log configure -state disabled
}
问题:此代码中有什么错误或遗漏? 你知道我可以用一个包或例子在一个单独的窗口上显示句子吗?
注意:我在macOS Sierra 10.12.5上使用tcl tk 8.6.6
答案 0 :(得分:2)
您的测试程序不是以事件驱动的方式编写的,因此更新屏幕的问题会加剧。
document.querySelector
语句将挂起程序,不允许重新输入事件循环。仅出于测试目的,请尝试:
after 10
而不是set ::w10 0
after 10 [list set ::w10 1]
vwait ::w10
命令。通常不建议使用after 10
命令,因为嵌套的vwait
将无法按预期工作。
当你有一个非常繁忙的循环时,Tk程序可能永远不会有机会重新进入其事件循环,并且永远不会更新显示。
最简单的解决方案是放一个
vwait's
update
程序结束时的语句。这并不总是处理此类问题的最佳方法,但它确实有效。
它还会减慢循环速度,因为每次写入日志消息时都必须重新绘制窗口。
另一种方法是将计算过程放入单独的线程或进程中,并将状态更新发送到主GUI进程。
答案 1 :(得分:0)
好吧,所以对于那些使用“ update”命令或“ update idletasks”命令的用户,您可能已经注意到,如果尝试在屏幕上四处移动GUI,则GUI或Text Widget将冻结。鼠标,甚至尝试最大化或调整其大小。这是使用此命令的副作用。它导致“外部事件”。导致GUI冻结或显示“无响应”。
输入以下两行代码代替“ update idletasks”,您将不会遇到此冻结问题:
500 {set go_on yes}之后
vwait go_on
答案 2 :(得分:-1)
我在使用几个不同的TCL脚本时遇到了同样的问题。我们所需要的只是一个基本的“文本”窗口,以在日志窗口或TK文本小部件中实时显示所有“输入”消息。
正如Brad所述,我发现最简单的解决方案是使用“ update”命令。我使用了命令“ update idletasks”,它对于文本小部件的“ puts”或“ insert”命令都非常有效。
这是我使用基本TK文本小部件的示例。 我使用了两个单独的过程。一个用于创建“文本记录”窗口,第二个用于在整个脚本中打印所需的消息。
结果是实时日志记录,而TCL脚本正在运行...并且在脚本完成时不会一次全部显示。感谢上帝!!!试图追踪如何做到这一点实在令人沮丧。最后,我了解了“更新”命令。 :P
proc REALTIME_TEXT_LOGGING {} {
# Creates a text widget
text .t -yscrollcommand ".scroll set" -setgrid true -width 40 -height 10 -wrap word
scrollbar .scroll -command ".t yview"
pack .scroll -side right -fill y
pack .t -expand yes -fill both
# Set up the tags
.t tag configure big -font {-family helvetica -size 24 -weight bold}
.t tag configure color1 -foreground red
.t tag configure sunken -relief sunken -borderwidth 1
#Button to activate the display of messages
button .b -text "PRINT MESSAGES TO THE LOG" \
-command {
Insert_Text "HELLO EVERYONE!! This is MSG #1"
after 5000
Insert_Text "HELLO EVERYONE!! This is MSG #2"
after 5000
Insert_Text "HELLO EVERYONE!! This is MSG #3"
after 5000
Insert_Text "HELLO EVERYONE!! This is MSG #4"
after 5000
Insert_Text "HELLO EVERYONE!! This is MSG #5"
}
.t window create end -window .b
}
proc Insert_Text {message} {
# Insert text that has the property of the tags from your TK text widget.
# I also used the "puts" command here, to show printing to the default TCL logging window.
.t insert end "$message\n"
puts "$message\n"
update idletasks
}