0

我无法修复spinbox. 具体来说,我需要在更改旋转框的值时通过它-commandupdate在其中更新 GUI。

稍微简化的代码如下:

  package require Tk
  set sv 1
  ttk::spinbox .sp -from 1 -to 9 -textvariable ::sv \
   -command {
     after 50                 ;# some processing imitated
     puts [incr ::tmp]:$::sv  ;# changes shown in CLI - ok
     update                   ;# changes shown in GUI - ???
   }
  pack .sp

问题是当单击旋转框的箭头(更多“向上”而不是“向下”,但我没有发现任何规律性)然后按下 10-20 秒时,旋转框进入无限循环更新,如图puts所示.

当然,原因update-command代码中,但我不能没有它。

在 Windows (Tk 8.6.8) 和 Linux (Tk 8.6.10) 中尝试过,ttk::spinbox并且spinbox,所有这些都暴露了怪胎。

有什么办法可以克服这个吗?非常感谢您的帮助。

4

2 回答 2

0

用视频制作了这个存档,update以演示当包含在其-command选项中时 spinbox 的奇怪行为。

存档中有两个测试:

test1.tcl提出了一种不应该这样做的方法。有两个问题:

  • -command代码未移至单独的过程
  • update立即从-command代码中触发

结果在test1-spx.mp4中看到:当按下旋转框箭头 10-20 秒时,旋转框进入无限循环更新。这种行为是不规则的,尽管当焦点切换到另一个应用程序时会很好地显示出来。

test2.tcl提供了一种克服这种怪癖的方法。after idle用于推迟更新。您也可以after 0为此使用。


在“真实测试” test2_pave.tcl 中,我使用以下过程-command

proc fontszCheck {} {
  lappend ::afters [after 0 {
    foreach a $::afters {after cancel $a}
    set ::afters [list]
    ::t::toolBut 4 -3
  }]
}

希望这些信息对处理 Tk spinbox 有用。

于 2020-11-19T09:54:38.443 回答
0

通常,不要从回调中更新 spinbox 变量-command,尤其不要update-command回调中运行。 你可能根本不应该这样做。该命令允许处理事件(它运行一个辅助事件循环,直到事件队列耗尽)并且正是您的问题的根源。(我也建议不要这样做update idletasks;这将触发问题核心的重新配置和重绘。)

相反,只需停止运行命令回调。这会将控制权返回给 Tk 小部件,而 Tk 小部件又将返回到主事件循环。还建议您不要在回调中进行大量处理,而是将此类处理安排在以后进行。究竟如何做到这一点可能很复杂,而且肯定是特定于应用程序的。稍后移动处理的一种方法是将其放到在after事件中运行的过程中,如下所示:

package require Tk
set sv 1
proc updateVar {varName} {
    upvar "#0" $varName var
    after 50;  # Processing...
    incr var;  # Actually update the variable
}
ttk::spinbox .sp -from 1 -to 9 -textvariable ::sv \
    -command {after 0 updateVar ::sv}
pack .sp

请注意,这不会调用update. 更实质性的代码延迟可能涉及线程或子进程。正如我所说,要做到这一点可能很复杂。尤其是当按下鼠标按钮时更改 GUI 布局会导致所选值发生更改,进而导致 GUI 布局发生更改……</p>

于 2020-11-18T10:44:48.290 回答