我正在尝试更改ttk组合框的下拉列表的宽度。设置组合框的宽度也会更改列表框的宽度,从而使部分值不可读。
我在Tk/Tcl中读到了this solution,但是我不熟悉这种语言,所以我想用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()
这里有没有人能帮我一下或者给我点建议?
发布于 2016-11-11 22:19:17
详细阐述patthoyts的优秀答案,使用派生样式而不是修改TCombobox
样式来获得通用的解决方案(但要注意Tk bug,稍后会有更多介绍)。
基本上,为每个组合框创建一个具有唯一名称的新样式(我不知道如何扩展-也许只在需要的地方应用它会更安全)。此外,Combobobox值是从小部件本身读取的,并且取最长的值:如果插入了短文本,还会检查以避免使popdown小于whe小部件。
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组合框中存在一个错误: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}]
或者,等待我的pull request被合并和释放。
发布于 2016-10-25 23:59:07
实现菜单发布的Tk库文件(ttk/combox.tcl)显式读取combobox小部件的宽度,并将菜单toplevel设置为相同的宽度(在ttk::combobox::PlacePopdown
中)。但是,您可以使用-postoffset
配置选项应用主题样式来覆盖此设置。这是为了允许某些主题偏移下拉列表,但我们可以将其设置为允许自定义宽度。注意:所有使用此样式的小部件都将获得相同的宽度,因此您可能希望派生出一个自定义样式。
在Tcl/Tk中,这是:ttk::style configure TCombobox -postoffset {0 0 300 0}
将下拉菜单设置为300像素宽(x,y,宽,高)。
更新
下面的python tkinter代码将一些代码添加到<Configure>
事件中,以获取combobox的大小并更新postoffset
宽度,以便dropdown将匹配字符串列表中第一个字符串的大小。结果如下所示:
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkfont
def on_combo_configure(event):
global fruit
font = tkfont.nametofont(str(event.widget.cget('font')))
width = font.measure(fruit[0] + "0") - event.width
style = ttk.Style()
style.configure('TCombobox', postoffset=(0,0,width,0))
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.bind('<Configure>', on_combo_configure)
c.pack()
root.mainloop()
我们使用事件绑定来做到这一点,因为这可以确保我们可以获得屏幕上小部件的实际大小,以便从偏移量中删除该宽度。
https://stackoverflow.com/questions/39915275
复制相似问题