tk/tcl几何管理器的怪异行为

tk/tcl几何管理器的怪异行为,tcl,tk,Tcl,Tk,我想设置窗口的宽度,为此,我使用以下代码: wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}] 将其设置为463像素宽。但当我只运行这一行时,窗口的高度设置为1。如果我在该行之前运行命令将带任何参数的,即使是没有新行的空字符串,也不会执行任何操作: puts -nonewline "" 然后我得到了正确的结果,即窗口的高度不是1。原因是什么?我如何解决该问题 关于正确编码标准的

我想设置窗口的宽度,为此,我使用以下代码:

wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]
将其设置为463像素宽。但当我只运行这一行时,窗口的高度设置为1。如果我在该行之前运行命令
将带任何参数的
,即使是没有新行的空字符串,也不会执行任何操作:

puts -nonewline ""
然后我得到了正确的结果,即窗口的高度不是1。原因是什么?我如何解决该问题


关于正确编码标准的评论:


我知道我在这里用的是a,这是一个非常糟糕的做法。这是我遇到的问题的临时解决方案,将来“幻数”将被替换为根据窗口与框架中其他窗口的关系计算的值,但是代码将是相同的,只是
463
将替换为
$width

,因为您没有显示创建该窗口的位置,我猜您在创建该窗口后不久就会执行该操作,例如:

toplevel .sigsetting_menu
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]
toplevel .sigsetting_menu
update idle
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]
问题是创建窗口需要时间,而且是分阶段进行的(我不是这方面的专家,所以我确定确切的过程),首先它创建窗口,然后再调整它的大小,但是TCL工作“太快”,所以它在调整原始窗口的大小之前调用第二行,使高度保持1px,但宽度改变。但是,当您调用类似于
put
的东西(这需要时间)时,它会成功地调整窗口的大小。 正确的方法是为这种情况调用一个特殊命令,该命令将停止当前代码的执行,直到事件循环为空。 所以你应该做一些类似的事情:

toplevel .sigsetting_menu
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]
toplevel .sigsetting_menu
update idle
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]

由于您没有显示要在何处创建该窗口,我猜您在创建该窗口后不久就会这样做,例如:

toplevel .sigsetting_menu
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]
toplevel .sigsetting_menu
update idle
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]
问题是创建窗口需要时间,而且是分阶段进行的(我不是这方面的专家,所以我确定确切的过程),首先它创建窗口,然后再调整它的大小,但是TCL工作“太快”,所以它在调整原始窗口的大小之前调用第二行,使高度保持1px,但宽度改变。但是,当您调用类似于
put
的东西(这需要时间)时,它会成功地调整窗口的大小。 正确的方法是为这种情况调用一个特殊命令,该命令将停止当前代码的执行,直到事件循环为空。 所以你应该做一些类似的事情:

toplevel .sigsetting_menu
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]
toplevel .sigsetting_menu
update idle
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]

Tk延迟窗口创建、几何计算(在设置窗口内容的过程中可能会非常复杂,而且几乎毫无意义)和内容的实际绘制,直到应用程序空闲为止,也就是说,直到它处于事件循环中并且没有待处理的实际事件为止。(从这个意义上讲,计时器事件在触发之前是不会挂起的。)这通常是正确的做法:它使Tk对于几乎所有正常代码来说都显得非常快。所有这些处理都是使用一个称为“空闲事件”的概念来处理的,Tk在内部使用了大量的空闲事件,您可以在空闲后通过
来创建自己的空闲事件

然而,上一段的结果是你不能直接做你想做的事;当您询问有关窗口几何体的当前信息时,它还没有被计算出来,因此您会得到一些(不相关的)默认值。您可以强制刷新挂起的空闲处理(使用
updateidletasks
,通常缩写为
updateidle
),但这可能会导致一些棘手的重入问题,并且还会触发不美观的显示闪烁(因为映射和绘图,您也无法阻止)。因此,您实际上应该做的是将几何体调整本身推迟到它们自己的空闲事件,如下所示:

after idle {
    wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] "463x"]
}
如果您要做很多这类事情,请使用helper过程使代码保持简单,并使用
list
生成回调(它完全正确地引用)



另外,您确定将宽度设置为明确的像素数是明智的吗?高分辨率显示即将到来……

Tk推迟窗口创建、几何计算(在设置窗口内容的过程中可能会非常复杂,而且几乎毫无意义)和内容的实际绘制,直到应用程序空闲,直到它在事件循环中并且没有待处理的实际事件为止。(从这个意义上讲,计时器事件在触发之前是不会挂起的。)这通常是正确的做法:它使Tk对于几乎所有正常代码来说都显得非常快。所有这些处理都是使用一个称为“空闲事件”的概念来处理的,Tk在内部使用了大量的空闲事件,您可以在空闲后通过
来创建自己的空闲事件

然而,上一段的结果是你不能直接做你想做的事;当您询问有关窗口几何体的当前信息时,它还没有被计算出来,因此您会得到一些(不相关的)默认值。您可以强制刷新挂起的空闲处理(使用
updateidletasks
,通常缩写为
updateidle
),但这可能会导致一些棘手的重入问题,并且还会触发不美观的显示闪烁(因为映射和绘图,您也无法阻止)。因此,您实际上应该做的是将几何体调整本身推迟到它们自己的空闲事件,如下所示:

after idle {
    wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] "463x"]
}
如果您要做很多这类事情,请使用helper过程使代码保持简单,并使用
list
生成回调(它完全正确地引用)



另外,您确定将宽度设置为明确的像素数是明智的吗?高分辨率显示即将到来…

在命令之前,窗口已经创建了很多,事实上,该命令是系统中的最后一个命令