Создайте собственный стиль ttk, такой же, как тема ttk 'clam' (зависит от виджета кнопки)

Мне нужно создать собственный стиль для виджетов кнопок, который имеет тот же внешний вид, что и кнопки, используя тему ttk 'clam'.

Я могу установить тему следующим образом:

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

Однако, учитывая характер темы, это затем установит для всех виджетов ttk использование «моллюска».

Я хотел бы иметь возможность настроить определенные кнопки ttk для использования внешнего вида моллюска, а другие - использовать ttk по умолчанию.

Я попытался просмотреть макеты и конфигурации «TButton», пока используется тема моллюска, но кажется, что тема представляет собой набор стилей, и я не уверен, как «сопоставить» пользовательский стиль на основе стиля кнопки моллюска. .


person Luke.py    schedule 21.03.2017    source источник


Ответы (1)


используя этот код:

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')

обратите внимание, что в теме моллюска есть элемент Button.border с параметрами, тогда как в нативной теме есть элемент Button.button без параметров.

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

РЕДАКТИРОВАТЬ теоретически это должно работать:

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()

однако по какой-то причине, когда я это делаю, текст больше не появляется на первой кнопке... если я выясню это, я снова отредактирую.

person James Kent    schedule 25.05.2017
comment
Привет, Джеймс. Спасибо за Ваш ответ! Я предполагаю, что вы используете Python x3, просматривая свои операторы печати? Когда я запускаю ваш код, я получаю следующую ошибку: print '%soption: %s' % (''.join(['\t' for s in range(depth+1)]), s.element_options(elem)) AttributeError: 'int' object has no attribute 'element_options' - Может ли это быть связано с Py 3x или другой версией Tkinter›? - person Luke.py; 25.05.2017
comment
извините, это разница между python2 и python3, использование s в качестве индекса перезаписало объект стиля внутри функции, теперь я изменил его на i и протестировал в python2.7 - person James Kent; 25.05.2017
comment
Спасибо, Джеймс, это действительно круто! - не могли бы вы уточнить, как вручную назначать кнопкам стиль, используя вывод сверху? - person Luke.py; 25.05.2017