问题
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