Tkinter OptionMenu:通过列表中最长的菜单项设置宽度

nit*_*k01 5 python tkinter

Tkinter会OptionMenu根据当前活动的菜单项设置其宽度。我正在寻找一种方法,使其根据最宽的菜单项设置其宽度,而不是根据当前选择的菜单项来设置宽度,以防止在用户选择其他菜单项时调整小部件的大小。

Tkinter选项菜单小组件更改宽度 ”问题中的建议答案隐藏了问题,但没有解决。(提示:不是重复的!)可接受的答案是将小部件设置为W和都具有粘性E。只要该列的建议大小比框中的所有项目都宽,就可以隐藏该问题,但实际上并不能解决问题。

我拥有(并且更愿意拥有)grid带有各种小部件的布局列,该列根据小部件的宽度动态调整大小。但是,我希望OptionMenu小部件报告的宽度是它最宽的项目的宽度,而不是当前选定的宽度,因为如果用户选择的项目比其他任何项目都要宽,则整列的宽度都会改变。

到目前为止,我发现的所有建议方法要么是粘住小部件,WE这并不能(本身)解决我的问题,然后设置与项目长度无关的任意恒定宽度,我不想做。

nit*_*k01 5

谢谢两个留下答案的人,但是都不希望使用单色字体或仅将宽度设置为字符串的长度。后者太不精确了,因为width参数在一个特殊的“文本单元”中采用一个数字,该数字对应于给定字体中字符“ 0”的宽度。因此,我的最终解决方案是执行以下操作:

  1. 找出元素使用的字体。
  2. 使用measure发现每串的宽度。(以像素为单位)。
  3. 用最长宽度除以0字符宽度。现在,您具有以“文本单位”表示的宽度。

这给出了以下代码。可能更像Pythonic,并且是OptionMenuetc 的子类的类方法,但是它可以工作。

def setMaxWidth(stringList, element):
    f = tkFont.nametofont(element.cget("font"))
    zerowidth=f.measure("0")
    w=max([f.measure(i) for i in stringList])/zerowidth

    element.config(width=w)
Run Code Online (Sandbox Code Playgroud)

出于好奇,我想知道调整后的宽度与数据中每个字符串的字符长度有何不同。这是一个简单的循环,其中包含来自我的字符串的经验数据。

    for i in stringList:
        print len(i), float(f.measure(i))/float(zerowidth)
Run Code Online (Sandbox Code Playgroud)

数据:

4 3.83333333333
24 20.1666666667
22 18.5
11 11.1666666667
12 11.3333333333
14 12.6666666667
Run Code Online (Sandbox Code Playgroud)

左列=字符串长度。右列=计算宽度。换句话说,len(max(opts, key=len))在所有情况下,幼稚的部件都会提供比所需的部件更大的部件。(这当然是可以预期的。)我还使用W重复.和重复的特殊情况比较了小部件的计算宽度,在所有情况下,这些人工测试字符串测试与小部件所要求的宽度非常吻合。通常”,无需手动设置宽度。