创建与“Clam”式ttk主题相同的自定义ttk样式(特定于按钮小部件)

发布于 2021-01-29 17:32:07

我需要使用ttk’clam’主题为按钮小部件创建一个与按钮外观相同的自定义样式。

我可以将主题设置为:

s = ttk.Style()
s.theme_use('clam')

但是,鉴于主题的性质,这会将所有ttk小部件设置为使用“Clam”。

我希望能够将某些ttk按钮设置为使用蛤appearance外观,而其他设置为使用默认的ttk。

我在尝试使用蛤theme主题时尝试查看“ TButton”的布局和配置,但似乎主题是样式的集合,我不确定如何根据Clambutton按钮样式“映射”自定义样式。

关注者
0
被浏览
50
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    使用此代码:

    import Tkinter as tk
    import ttk
    
    def get_element_details(style):
        print('element: %s' % style)
        print('option: %s' % str(s.element_options(style)))
        layout = s.layout(style)
        for elem, elem_dict in layout:
            get_sub_element_details(elem, elem_dict)
        print(layout)
    
    def get_sub_element_details(elem, _dict, depth=1):
        print('%selement: %s' % (''.join(['\t' for i in range(depth)]), elem))
        for key in _dict:
            if key != 'children':
                print('%s%s: %s' % (''.join(['\t' for i in range(depth+1)]), key, _dict[key]))
        print('%soption: %s' % (''.join(['\t' for i in range(depth+1)]), s.element_options(elem)))
        if 'children' in _dict:
            for child, child_dict in _dict['children']:
                get_sub_element_details(child, child_dict, depth+1)
    
    root = tk.Tk()
    widget = ttk.Button(root, text='test')
    widget.grid(sticky='nesw')
    
    style = widget.winfo_class()
    
    s = ttk.Style()
    
    print(s.theme_use())
    print('normal theme')
    get_element_details(style)
    
    print('\nclam theme')
    s.theme_use('clam')
    get_element_details(style)
    

    您可以提供有关小部件的所有布局和配置选项的详细信息。在本机(xp)上使用本机主题,我得到以下输出:

    element: TButton
    option: ()
        element: Button.button
            sticky: nswe
            option: ()
            element: Button.focus
                sticky: nswe
                option: ()
                element: Button.padding
                    sticky: nswe
                    option: ('-padding', '-relief', '-shiftrelief')
                    element: Button.label
                        sticky: nswe
                        option: ('-compound', '-space', '-text', '-font', '-foreground', '-underline', '-width', '-anchor', '-justify', '-wraplength', '-embossed', '-image', '-stipple', '-background')
    

    并以蛤为主题,我得到:

    element: TButton
    option: ()
        element: Button.border
            border: 1
            sticky: nswe
            option: ('-bordercolor', '-lightcolor', '-darkcolor', '-relief', '-borderwidth')
            element: Button.focus
                sticky: nswe
                option: ('-focuscolor', '-focusthickness')
                element: Button.padding
                    sticky: nswe
                    option: ('-padding', '-relief', '-shiftrelief')
                    element: Button.label
                        sticky: nswe
                        option: ('-compound', '-space', '-text', '-font', '-foreground', '-underline', '-width', '-anchor', '-justify', '-wraplength', '-embossed', '-image', '-stipple', '-background')
    

    请注意,clam主题的Button.border元素带有选项,而本机主题的Button.button元素带有选项。

    您可以从clam主题中保存布局(在编写时,或者可以在运行时通过加载clam主题,获取布局然后切换回主题并重新加载布局来获取布局),然后使用该样式来设置按钮的样式。

    理论上,这应该工作:

    import Tkinter as tk
    import ttk
    
    root = tk.Tk()
    
    style = 'TButton'
    
    s = ttk.Style()
    
    #s.theme_use('clam')
    
    #get_element_details(style)
    
    clambuttonlayout = [('Button.border', {'border': '1', 'children': [('Button.focus', {'children': [('Button.padding', {'children': [('Button.label', {'sticky': 'nswe'})], 'sticky': 'nswe'})], 'sticky': 'nswe'})], 'sticky': 'nswe'})]
    
    s.layout('clam.TButton', clambuttonlayout)
    
    b1 = ttk.Button(root, text="Button 1", style='clam.TButton')
    b1.grid()
    b2 = ttk.Button(root, text="Button 2", style='TButton')
    b2.grid()
    
    root.mainloop()
    

    但是由于某种原因,当我执行此操作时,该文本将不再出现在第一个按钮上…如果我知道了,我将再次进行编辑。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看