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

时间:2014-02-17 07:32:26

标签: python tkinter

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

问题Tkinter Option Menu Widget Changing Widths中的建议答案隐藏了问题,但没有解决问题。 (提示:不重复!)接受的答案是将小部件设置为对WE都是粘性的。只要列的建议大小比框中的所有项目都宽,但这实际上没有解决问题,这就隐藏了问题。

我有(并且更喜欢)具有各种小部件的grid布局列,其基于小部件的宽度动态调整大小。但是,我更喜欢OptionMenu窗口小部件报告的宽度是最宽的项目,而不是当前选择的宽度,因为如果用户选择的项目宽度大于整个列的宽度。任何其他项目。

到目前为止我找到的所有建议方法都是粘贴小部件WE,它不会(本身)解决我的问题,并设置任意常量宽度与项目长度无关,我不想这样做。

3 个答案:

答案 0 :(得分:4)

感谢两位留下答案的人,但是既不使用单色字体也不只是将宽度设置为字符串的长度是理想的解决方案。后者太不精确,因为width参数在与给定字体中字符“0”的宽度相对应的特殊“文本单元”中取一个数字。所以我的最终解决方案如下:

  1. 找出元素使用的字体。
  2. 使用measure查找每个字符串的宽度。 (以像素为单位给出。)
  3. 将最长宽度除以0字符的宽度。您现在的宽度为“文本单位”。
  4. 这给出了以下代码。可能更像Pythonic并且是OptionMenu等子类的类方法,但它可以工作。

    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)
    

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

        for i in stringList:
            print len(i), float(f.measure(i))/float(zerowidth)
    

    数据:

    4 3.83333333333
    24 20.1666666667
    22 18.5
    11 11.1666666667
    12 11.3333333333
    14 12.6666666667
    

    左列=字符串长度。右栏=计算的宽度。换句话说,天真的len(max(opts, key=len))会在所有情况下提供比需要更大的小部件。 (这当然是可以预料到的。)我还使用重复W的特殊情况以及重复的.来比较小部件的计算宽度,并且在所有情况下,这些人工测试字符串测试与“正常”小部件请求的宽度一致,没有手动设置宽度。

答案 1 :(得分:2)

如果您的GUI使用固定宽度的字体,您可以获得填充OptionMenu的列表中最长元素的长度,并根据该值设置宽度。

from Tkinter import *

root = Tk()

opts = ['bacon', 'cereal', 'eggs']

oMenuWidth = len(max(opts, key=len))

v = StringVar(root)
v.set(opts[0])
oMenu = OptionMenu(root, v, *opts)
oMenu.config(width=oMenuWidth)
oMenu.grid()

mainloop()

我想即使它不是固定长度,你可以在实现之前对宽度执行数学运算,使其接近正确。

答案 2 :(得分:1)

这是您的两个选择:设置固定宽度,或依靠单元格的宽度来控制窗口小部件的宽度。设置非任意固定宽度应该是微不足道的,因为您是设置窗口小部件内容的人。只需跟踪放在窗口小部件中的最宽项目,并将该宽度用作窗口小部件的所需宽度。