更改 ttk 组合框的下拉列表框的宽度

新手上路,请多包涵

我正在尝试更改为 ttk Combobox 的弹出列表的宽度。设置 Combobox 的宽度也会改变 Listbox 的宽度,使部分值不可读。

我在 Tk/Tcl 中阅读 了这个解决方案,但我不熟悉这种语言,想用 Python 解决问题。我尝试更改主题参数,但似乎无济于事。下面是一段示例代码。

 import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.title("testing the combobox")
root.geometry('300x300+50+50')
fruit = ['apples are the best', 'bananas are better']

c = ttk.Combobox(root, values=fruit, width=10)
c.pack()

# Trying to change the width, does not work
c.option_add("*TCombobox*Listbox*Width", 50)

root.mainloop()

这里有人可以帮助我或给我一些指示吗?

原文由 Raoul Collenteur 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 810
1 个回答

patthoyts 的详细回答是使用派生样式而不是修改 TCombobox 样式来获得通用解决方案(但要注意 Tk 错误,稍后会详细介绍)。

基本上,为每个组合框创建一个具有唯一名称的新样式(我不知道这如何扩展 - 也许只在需要的地方应用它更安全)。此外,组合框值是从小部件本身读取的,并且取最长的一个:如果插入短文本,还有一个检查以避免使弹出窗口小于小部件。

 import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkfont

def on_combo_configure(event):
    combo = event.widget
    style = ttk.Style()
    # check if the combobox already has the "postoffest" property
    current_combo_style = combo.cget('style') or "TCombobox"
    if len(style.lookup(current_combo_style, 'postoffset'))>0:
        return
    combo_values = combo.cget('values')
    if len(combo_values) == 0:
        return
    longest_value = max(combo_values, key=len)
    font = tkfont.nametofont(str(combo.cget('font')))
    width = font.measure(longest_value + "0") - event.width
    if (width<0):
        # no need to make the popdown smaller
        return
    # create an unique style name using widget's id
    unique_name='Combobox{}'.format(combo.winfo_id())
    # the new style must inherit from curret widget style (unless it's our custom style!)
    if unique_name in current_combo_style:
        style_name = current_combo_style
    else:
        style_name = "{}.{}".format(unique_name, current_combo_style)

    style.configure(style_name, postoffset=(0,0,width,0))
    combo.configure(style=style_name)

root = tk.Tk()
root.title("testing the combobox")
root.geometry('300x300+50+50')
fruit = ['apples are the best', 'bananas are way more better']

c = ttk.Combobox(root, values=fruit, width=10)
c.bind('<Configure>', on_combo_configure)
c.pack()

c1 = ttk.Combobox(root, values=['shorter','than','widget'], width=15)
c1.bind('<Configure>', on_combo_configure)
c1.pack()

root.mainloop()

但…

如前所述,Tk Combobox 中存在一个错误: postoffest 属性只能从 TCombobox 样式中读取,而不是从派生样式中读取。

这可以通过编辑 [python-install-dir]\tcl\tk[version]\ttk\combobox.tcl 来修复;在 PlacePopdown 方法中找到这一行:

 set postoffset [ttk::style lookup TCombobox -postoffset {} {0 0 0 0}]

并将其替换为:

 set style [$cb cget -style]
set postoffset [ttk::style lookup $style -postoffset {} {0 0 0 0}]

或者,等待我的 拉取请求 被合并和发布。

原文由 dipanda 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进