ttk.Combobox在状态为只读且失焦时出现故障

时间:2013-09-04 09:46:26

标签: python python-3.x combobox tkinter ttk

当ttk.Combobox是只读且不在焦点时,其文本背景变为白色,与灰色场背景不同,使组合框看起来很丑:

Example

所需的风格将是第二个。如何使组合框像这样工作?

2 个答案:

答案 0 :(得分:7)

解决方案是改变ttk样式:

s = ttk.Style()
s.map("TCombobox",
    selectbackground=[
        ('!readonly', '!focus', 'SystemWindow'),
        ('readonly', '!focus', 'SystemButtonFace'),
        ],
    )

这会改变全局组合框的行为。在下面的演示中(从中可以看到问题的屏幕截图)我为一个漂亮的工作组合框定义了一个自定义样式为“Alt.TCombobox”并使用了它:

# cboxdemo.py by Adam Szieberth (2013)
# Python 3.3.0

"""Read-only Ttk.Combobox style demo module.

The style of the second combobox has been slightly modified to
make text background match with combobox background when out of
focus.

In read-only state (which is default) you can notice that text
background gets white in the first (original styled) combobox
when focus moves towards. Second combobox looks nice then.

With the button you can test that the two works exactly the same
in writeable state.
"""

from random import randint
from tkinter import Button, Frame, StringVar, Tk
from tkinter.ttk import Combobox, Style

class App(Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.state = None
        self.style = Style()
        self.style.map("Alt.TCombobox",
            selectbackground=[
                ('!readonly', '!focus', 'SystemWindow'),
                ('readonly', '!focus', 'SystemButtonFace'),
                ],
            )
        self.button = Button(self, text="Change state!",
            command=self.switch)
        self.cbox1var, self.cbox2var = StringVar(), StringVar()
        self.cbox1 = Combobox(self,
            exportselection=0,
            values=["sex", "sleep", "eat", "drink", "dream",],
            textvariable=self.cbox1var,
            )
        self.cbox1.bind('<<ComboboxSelected>>', self.bfocus)
        self.cbox1.current(1)
        self.cbox2 = Combobox(self,
            exportselection=0,
            values=["fear", "clarity", "power", "old age",],
            style="Alt.TCombobox",
            textvariable=self.cbox2var,
            )
        self.cbox2.bind('<<ComboboxSelected>>', self.bfocus)
        self.cbox2.current(3)
        self.cbox1.pack()
        self.cbox2.pack()
        self.button.pack()
        self.switch()

    def bfocus(self, *args):
        if randint(0,1):
            self.button.focus()
            print('Focus moved!')
        else:
            print('Focus stayed.')

    def switch(self):
        if self.state == ['readonly']:
            self.state = ['!readonly']
            print('State is writeable!')
        else:
            self.state = ['readonly']
            print('State is read-only!')
        self.cbox1.state(self.state)
        self.cbox2.state(self.state)

if __name__ == "__main__":
    root = Tk()
    root.title('ttk.Combobox styling')
    App(root).pack()
    root.mainloop()

答案 1 :(得分:1)

另一种实现方法可能是:

from tkinter.ttk import Combobox, Style

style = Style()
style.theme_create('custom_style',
                   parent='default',
                   settings={'TCombobox':
                             {'configure':
                              {'selectforeground': 'black',
                               'selectbackground': 'white'}
                              }
                             }
                   )
style.theme_use('custom_style')

现在,您创建一个简单的组合框。

cb = Combobox(frame1, state='readonly')
cb['values'] = [
    'Please select',
    'Option 1',
    'Option 2',
    'Option 3'
]
cb.current(0)
cb.bind('<<ComboboxSelected>>', my_function_to_exec)
cb.grid(row=0, column=0, sticky='w')

这不会使文本保持选中状态。作为“主题”完成后,这将适用于所有组合框。