2025, Oct 18 22:16

Почему текст в ttk.Combobox пропадает в теме clam и как это исправить

Исправляем баг темы clam в Tkinter: в readonly ttk.Combobox выбранный текст «исчезает» из‑за цвета foreground. Разбираем причину и даем стиль ttk.Style.map.

При стилизации ttk.Combobox в Tkinter с темой clam можно столкнуться с неожиданным UX-эффектом: после взаимодействия с выпадающим списком выбранный текст будто исчезает. Значение остаётся, но его не видно. В темах вроде alt этот эффект не проявляется, поэтому проблема выглядит специфичной для темы и кажется непоследовательной.

Воспроизведение проблемы

Ниже приведён пример readonly-Combobox под темой clam с белыми фонами. Во время взаимодействия выбранный пункт становится невидимым.

import tkinter as tk, tkinter.ttk as ttk

app = tk.Tk()

styler = ttk.Style(app)
styler.theme_use("clam")
styler.configure("TCombobox", fieldbackground="white", background="white")
styler.map("TCombobox", fieldbackground=[["readonly", "white"]], background=[["readonly", "white"]])

chooser = ttk.Combobox(app, state="readonly", values=("apples", "oranges", "bananas"))
chooser.set("apples")
chooser.pack(padx=40, pady=40)

app.mainloop()

Что на самом деле происходит

В теме clam цвет текста (foreground) по умолчанию для состояния readonly при наличии фокуса — белый. Если fieldbackground тоже белый, текст фактически сливается с полем. Отсюда и ощущение, что значение пропадает.

Исправление оформления

Решение — явно сопоставить читаемый цвет текста с нужным состоянием. Если установить чёрный foreground для Combobox в состояниях readonly и focus, текст снова будет виден.

import tkinter as tk, tkinter.ttk as ttk

app = tk.Tk()

styler = ttk.Style(app)
styler.theme_use("clam")
styler.configure("TCombobox", fieldbackground="white", background="white")
styler.map(
    "TCombobox",
    fieldbackground=[["readonly", "white"]],
    background=[["readonly", "white"]],
    foreground=[["readonly", "focus", "black"]]
)

chooser = ttk.Combobox(app, state="readonly", values=("apples", "oranges", "bananas"))
chooser.set("apples")
chooser.pack(padx=40, pady=40)

app.mainloop()

При желании можно задать цвет текста для readonly и без учёта фокуса.

Почему эта деталь важна

Тематические оформления интерфейса задают разумные значения по умолчанию, но ваши настройки могут незаметно конфликтовать с ними. В нашем случае простая смена фона «спрятала» текст из‑за сопоставления состояний, заданного темой. Понимание того, как работает ttk.Style.map и как взаимодействуют состояния вроде readonly и focus, помогает избежать визуальных регрессий и сохраняет читабельность виджета при разных сценариях взаимодействия.

Выводы

Переопределяя fieldbackground или другие визуальные свойства ttk‑виджетов, обязательно проверьте сопоставления для foreground — особенно для конкретных состояний, которые использует ваша тема. Небольшая явная карта состояний для foreground обеспечивает стабильную читабельность и убережёт от сюрпризов вроде «исчезающего» выбора в ttk.Combobox под темой clam.

Статья основана на вопросе на StackOverflow от vengy и ответе от acw1668.