【问题标题】:Tcl/tk - Get window height and width and set relative text height in gridTcl/tk - 获取窗口高度和宽度并在网格中设置相对文本高度
【发布时间】:2016-07-08 04:39:32
【问题描述】:

我想创建一个窗口,其中包含两个文本框,一个在另一个之上,第一个占据 25% 的高度,下一个占据 75% 的高度。

我试图计算顶层 win 的相对高度/宽度并传递给 text 命令但没有用(我猜是因为 wm 几何返回的尺寸单位与传递给 text 命令时的尺寸单位不同)

以下是我的代码:

toplevel .t
wm geometry .t 1500x800+10+10
update
proc topAspect {args} {
    regexp {(\d+)} $args -> relAspect
    regexp {([^\d|%]+)} $args -> aspect
    regexp {(.*)x(.*)[+-](.*)[+-](.*)} [wm geometry .t] -> width height x y
    puts "width->$width height->$height x->$x y->$y"
    switch -regexp [string tolower $aspect] {
        x {
            return [expr $x + $relAspect]
        }
        y {
            return [expr $y + $relAspect]
        }
        w {
            return [expr $width * $relAspect / 100]
        }
        h {
            return [expr $height * $relAspect / 100]
        }
        default {
            log::log error "Unsupported relative aspect $aspect cannot be determined for top level window"
        }
    }
}

text  .t.text1 -height [topAspect -width 25%] -width [topAspect -width 99%]
grid .t.text1 -sticky news
text  .t.text2 -height [topAspect -width 75%] -width [topAspect -width 99%]
grid .t.text2 -sticky news

当我尝试跟随时 - 它确实给了我一些不错的 GUI:

text  .t.text1 -height 20 -width [topAspect -width 99%]
grid .t.text1 -sticky news
text  .t.text2 -height 20 -width [topAspect -width 99%]
grid .t.text2 -sticky news

但我想使用相对选项。如何让它发挥作用?

【问题讨论】:

    标签: tcl tk


    【解决方案1】:

    解决此问题的最简单方法是使用具有正确比例权重和统一组的网格几何管理器。当您调整窗口大小时,它甚至可以正常工作; Tk 了解政策本身并为您维护它。 (在内部,grid 是一个相当复杂的约束求解器;你可以用它来做一些真正复杂的事情。)

    toplevel .t
    grid [text .t.text1 -bg red]   -sticky news
    grid [text .t.text2 -bg green] -sticky news
    
    # The group name is just an arbitrary non-empty string.
    # So long as it is the same on the two rows it will work as desired.
    # The weights give a ratio of 1:3, i.e., 25% to one and 75% to the other.
    
    grid rowconfigure .t .t.text1 -weight 1 -uniform group1
    grid rowconfigure .t .t.text2 -weight 3 -uniform group1
    

    (如果您使用的是 Tk 8.5,则需要通过数字而不是行中小部件的通常更方便的名称来指定行到 rowconfigure。)

    【讨论】:

      【解决方案2】:

      是的,text 小部件的 -height-width 选项以字符单位而不是屏幕单位给出。您可以通过进一步除以字体宽度和高度来解决这个问题(我将它们设置为下面的常量值)。请记住,这是整数除法!

      哦,所有这些正则表达式......我已经清理了一点,你可以接受或离开它。

      proc topAspect {aspect relAspect} {
          set relAspect [string trimright $relAspect %]
          scan [wm geometry .t] "%dx%d%d%d" width height x y
          set fontWidth 15
          set fontHeight 15
          switch -regexp [string tolower $aspect] {
              x {
                  return [expr {$x + $relAspect}]
              }
              y {
                  return [expr {$y + $relAspect}]
              }
              w {
                  return [expr {($width * $relAspect / 100) / $fontWidth}]
              }
              h {
                  return [expr {($height * $relAspect / 100) / $fontHeight}]
              }
              default {
                  log::log error "Unsupported relative aspect $aspect cannot be determined for top level window"
              }
          }
      }
      

      另外,对于-height-width,您使用-width 作为topAspect 的参数:我认为这是一个错误。

      text  .t.text1 -height [topAspect -height 25%] -width [topAspect -width 99%]
      grid .t.text1 -sticky news
      text  .t.text2 -height [topAspect -height 75%] -width [topAspect -width 99%]
      grid .t.text2 -sticky news
      

      否则,我推荐 Donal Fellows 的解决方案。

      文档: * (operator), + (operator), / (operator), expr, for, grid, proc, return, scan, set, string, switch, text (widget), wm, Syntax of Tcl regular expressions

      【讨论】:

      • 需要注意解析几何输出,因为它在多显示器设置中可能有负偏移。例如:200x200+-638+77 我的。所以scan 正确解析的语句是[scan $geometry "%dx%d+%d+%d"],它能够处理否定。
      • 感谢指正,我误解了格式的文档。但根据我目前的理解,前缀可能是 - 以及 +,可能后跟 g 数字的符号。如果是这样,则必须通过{%dx%d%*1[+-]%d%*1[+-]%d} 或正则表达式{(\d+)x(\d+)[+-]([+-]?\d+)[+-]([+-]?\d+)} 对其进行扫描。
      • WxH-X+Y 格式(使用 X 偏移量的前导减号表示位置是从屏幕的右端开始 -- 参见 tkWinWm.c 中 WM_NEGATIVE_X 上的 cmets。所以可能我们可以得到1x1--2+3 我认为是的。看起来正则表达式是必要的。
      • 扫描模式仍然更简单,但我不会反对任何想要使用正则表达式的人。
      • 还有可选的前导=,大小可选:{=?((\d+)x(\d+))?([+-])(-?\d+)([+-])(-?\d+)}。我使用 X 文档来确定这个正则表达式。我不知道...++456 是否有效。我猜不是。
      【解决方案3】:

      Place 在这种情况下效果最好 - 即使在调整以下大小时也能很好地保持比例:

      place .t.text1  -in .t -relheight .25 -relwidth .98 -relx .003 -rely .003
      place .t.text2 -in .t -relheight .75 -relwidth .98 -relx .003 -rely .254
      

      与网格相比,任何人在这种方法中看到的任何缺陷。

      谢谢

      【讨论】:

      • place 这样使用的主要问题是它不会将大小传播到包含的小部件。这对您来说可能很重要,也可能无关紧要,这取决于您的 GUI 的其余部分发生了什么。您也可以通过绑定到右侧小部件上的 <Configure> 事件来修复它,但那时事情会变得相当复杂。
      • 好的 - 我会按照你的建议使用网格,如果效果很好,我会使用相同的 - 再次感谢
      猜你喜欢
      • 2018-06-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-20
      • 1970-01-01
      相关资源
      最近更新 更多