1

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

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

将其设置为 463 像素宽。但是当我只运行这一行时,窗口的高度设置为 1。如果我在该行之前运行puts带有任何参数的命令,即使是没有新行的空字符串,它什么也不做:

puts -nonewline ""

然后我得到正确的结果,即窗口的高度不是 1。是什么原因造成的,我该如何解决这个问题?


评论正确的编码标准:

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

4

2 回答 2

4

Tk 推迟窗口创建、几何计算(在设置窗口内容期间可能相当复杂且几乎毫无意义)和内容的实际绘制,直到应用程序处于空闲状态,即直到它处于事件循环中并且有没有待处理的真实事件。(从这个意义上说,定时器事件在它们触发之前不会挂起。)这通常是正确的做法:它使 Tk 对于几乎所有正常代码来说看起来都非常快。所有这些处理都是使用称为“空闲事件”的概念来处理的,Tk 在内部使用了很多,您可以使用 via 制作自己的after idle

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

after idle {
    wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] "463x"]
}

如果您要做很​​多此类事情,请使用帮助程序来保持您的代码简单并list生成回调(它完全正确地引用)。

proc setGeometryWidth {window width} {
    wm geometry $window [regsub {\d+x} [wm geometry $window] "${width}x"]
}
after idle [list setGeometryWidth .sigsetting_menu 463]

另外,您确定将宽度设置为明确的像素数是否明智?高分辨率显示器即将问世……</p>

于 2013-06-16T17:47:28.273 回答
1

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

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

问题是创建窗口需要时间并且它分阶段进行(我不是这方面的专家,所以我确定确切的过程),首先它是创建窗口,然后才调整它的大小,但 TCL 工作“太快”,所以它在调整原始窗口大小之前调用第二行,因此高度保持 1px 但宽度发生变化。但是当你调用类似puts需要时间的东西时,它会设法正确调整窗口大小。正确的方法是调用一个特殊的命令来处理这种情况 update,它会停止当前代码的执行,直到事件循环为空。因此,您应该执行以下操作:

toplevel .sigsetting_menu
update idle
wm geometry .sigsetting_menu [regsub {\d+x} [wm geometry .sigsetting_menu] {463x}]
于 2013-06-16T15:28:16.263 回答