Изменить ширину обновленного списка в поле ttk Combobox - PullRequest
0 голосов
/ 20 апреля 2020

Это расширение вопроса и ответов здесь .

Я хочу создать два комбинированных списка, элементы которых во втором комбинированном списке зависят от выбора в первом комбинированном списке. Кроме того, я бы хотел, чтобы размер выпадающего списка изменялся в соответствии с текстом в списке, как в ответе здесь . Однако у меня возникли некоторые трудности с этой второй частью. Я хотел бы решить эту проблему, используя Python.

. У меня были разные результаты с использованием .pack () и .forget () вместо .place () и .place_forget (), однако у меня нет не удалось создать надежное решение. Использование .place предпочтительнее .pack или .grid, если это возможно.

Как MWE, я расширил код из одного из ответов в предыдущем вопросе. Размер выпадающего списка c2 изменяется нормально, а c1 - нет.

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)

def update_c1_list(event):
    c1.place_forget()
    _ = c.get()
    if _ == "fruit":
        c1['values'] = ('apples are the best', 'bananas are way more better')
    elif _ == "text":
        c1['values'] = ("here's some text", "and here's some much longer text to stretch the list")
    else:
        pass
    c1.place(x=10,y=40)

root = tk.Tk()
root.title("testing the combobox")
root.geometry('300x300+50+50')

c = ttk.Combobox(root, values=['fruit','text'], state="readonly", width=10)
c.bind('<Configure>', on_combo_configure)
c.bind('<<ComboboxSelected>>', update_c1_list)
c.place(x=10,y=10)

c1 = ttk.Combobox(root, state="readonly", width=10)
c1.bind('<Configure>', on_combo_configure)
c1.place(x=10,y=40)

c2 = ttk.Combobox(root, state="readonly", width=10)
c2.bind('<Configure>', on_combo_configure)
c2.place(x=10,y=70)
c2['values']=('this list resizes fine','because it is updated outside of the function')

root.mainloop()

Любая помощь приветствуется, спасибо.

1 Ответ

0 голосов
/ 23 апреля 2020

После игры у меня появилась функция, которая обновляет ширину списка со списком "на лету". Однако это немного похоже на исправление окна с помощью молотка и вызывает некоторые проблемы.

def Change_combo_width_on_the_fly(combo,combo_width):
style = ttk.Style()
# check if the combobox already has the "postoffest" property
current_combo_style = combo.cget('style') or "TCombobox"
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") - (combo_width*6+23)
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)

В качестве MWE код можно использовать следующим образом:

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

root = tk.Tk()
c1 = ttk.Combobox(root, state="readonly", width=10)
c1.place(x=10,y=40)
Change_combo_width_on_the_fly(c1,10)
root.mainloop()

В то время как функция делает работу, это вызывает проблемы в другом месте в моем коде. В частности, это портит ранее упакованный виджет (полоса прокрутки). Я думаю, что это меняет стиль последнего размещенного виджета, но я не знаю, как это исправить.

...