How to make border around ttk.OptionMenu

烈酒焚心 提交于 2020-01-24 09:50:27

问题


While trying to make an entry frame I ran into a problem where I can't make border around ttk.OptionMenu in order to make it look similiar to ttk.Entry. (The two next to each other are in image)

Making OptionMenu

option = ttk.OptionMenu(bottom_container, self.have, 'ANY', 'ANY', '0', '1', style='vista.TMenubutton')
option.grid(column=1, row=2, sticky='we')

I tried using styles (want to still use vista/winnative look) and was able to make the optionmenu background white, but I couldn't find a way to fit in a border around it


回答1:


this is the code i use for inspecting ttk widgets with a view to working out how to theme them:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
var = tk.StringVar()
widget = ttk.OptionMenu(root, var, 'ANY', 'ANY', '0', '1')
widget.grid(column=2, row=1, sticky='nesw')


style = widget.winfo_class()

s = ttk.Style()
#s.theme_use('clam')
elements = s.layout(style)

def get_element_details(elem, _dict, depth=1):
    print('%selement: %s' % (''.join(['\t' for s in range(depth)]), elem))
    for key in _dict:
        if key != 'children':
            print('%s%s: %s' % (''.join(['\t' for s in range(depth+1)]), key, _dict[key]))
    print('%soption: %s' % (''.join(['\t' for s in range(depth+1)]), s.element_options(elem)))
    if 'children' in _dict:
        for child, child_dict in _dict['children']:
            get_element_details(child, child_dict, depth+1)

print('element: %s' % style)
print('option: %s' % str(s.element_options(style)))
for elem, elem_dict in elements:
    get_element_details(elem, elem_dict)
root.mainloop()

and to put it simply without switching the theme to something like the clam theme there isn't any options in the widget to add a border (stupid I know)

i don't have the vista theme to test with, but with the XP theme i get:

element: TMenubutton
option: ()
    element: Menubutton.dropdown
        side: right
        sticky: ns
        option: ()
    element: Menubutton.button
        expand: 1
        sticky: nswe
        option: ()
        element: Menubutton.padding
            expand: 1
            sticky: we
            option: ('-padding', '-relief', '-shiftrelief')
            element: Menubutton.label
                sticky: 
                option: ('-compound', '-space', '-text', '-font', '-foreground', '-underline', '-width', '-anchor', '-justify', '-wraplength', '-embossed', '-image', '-stipple', '-background')

and with the clam theme:

element: TMenubutton
option: ()
    element: Menubutton.border
        sticky: nswe
        option: ('-bordercolor', '-lightcolor', '-darkcolor', '-relief', '-borderwidth')
        element: Menubutton.focus
            sticky: nswe
            option: ('-focuscolor', '-focusthickness')
            element: Menubutton.indicator
                sticky: 
                side: right
                option: ('-arrowsize', '-arrowcolor', '-arrowpadding')
            element: Menubutton.padding
                expand: 1
                sticky: we
                option: ('-padding', '-relief', '-shiftrelief')
                element: Menubutton.label
                    sticky: 
                    side: left
                    option: ('-compound', '-space', '-text', '-font', '-foreground', '-underline', '-width', '-anchor', '-justify', '-wraplength', '-embossed', '-image', '-stipple', '-background')

notice the addition of the border element?

and if you try to copy the layout of the clam theme optionmenu to another theme using:

newlayout = [('Menubutton.border', {'children': [('Menubutton.focus', {'children': [('Menubutton.indicator', {'sticky': '', 'side': 'right'}), ('Menubutton.padding', {'sticky': 'we', 'expand': '1', 'children': [('Menubutton.label', {'sticky': '', 'side': 'left'})]})], 'sticky': 'nswe'})], 'sticky': 'nswe'})]
s.layout(style, newlayout)

the result is:

element: TMenubutton
option: ()
    element: Menubutton.border
        sticky: nswe
        option: ('-relief',)
        element: Menubutton.focus
            sticky: nswe
            option: ()
            element: Menubutton.indicator
                sticky: 
                side: right
                option: ('-direction', '-arrowsize', '-arrowcolor')
            element: Menubutton.padding
                sticky: we
                expand: 1
                option: ('-padding', '-relief', '-shiftrelief')
                element: Menubutton.label
                    sticky: 
                    side: left
                    option: ('-compound', '-space', '-text', '-font', '-foreground', '-underline', '-width', '-anchor', '-justify', '-wraplength', '-embossed', '-image', '-stipple', '-background')

which no longer has options for actually setting the border. essentially the theme engine cannot properly handle layouts which have different elements to which it is expecting. so you will need to chose a theme which has widgets with all the elements you want to style.



来源:https://stackoverflow.com/questions/51534878/how-to-make-border-around-ttk-optionmenu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!