终端文本未实时显示在tcltk窗口中

时间:2017-07-25 12:47:14

标签: window tcl tk

我对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

3 个答案:

答案 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 
}