Bootstyle
ttkbootstrap.style.Bootstyle
override_tk_widget_constructor(func)
staticmethod
Override widget constructors to apply default style for tk widgets.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Callable |
The |
required |
Source code in ttkbootstrap/style.py
@staticmethod
def override_tk_widget_constructor(func):
"""Override widget constructors to apply default style for tk
widgets.
Parameters:
func (Callable):
The `__init__` method for this widget.
"""
def __init__wrapper(self, *args, **kwargs):
# check for autostyle flag
if "autostyle" in kwargs:
autostyle = kwargs.pop("autostyle")
else:
autostyle = True
# instantiate the widget
func(self, *args, **kwargs)
if autostyle:
Publisher.subscribe(
name=str(self),
func=lambda w=self: Bootstyle.update_tk_widget_style(w),
channel=Channel.STD,
)
Bootstyle.update_tk_widget_style(self)
return __init__wrapper
override_ttk_widget_configure(func)
staticmethod
Overrides the configure method on a ttk widget.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Callable |
The widget class |
required |
Source code in ttkbootstrap/style.py
@staticmethod
def override_ttk_widget_configure(func):
"""Overrides the configure method on a ttk widget.
Parameters:
func (Callable):
The widget class `configure` method
"""
def configure(self, cnf=None, **kwargs):
# get configuration
if cnf in ("bootstyle", "style"):
return self.cget("style")
if cnf is not None:
return func(self, cnf)
# set configuration
if "bootstyle" in kwargs:
bootstyle = kwargs.pop("bootstyle")
else:
bootstyle = ""
if "style" in kwargs:
style = kwargs.get("style")
ttkstyle = Bootstyle.update_ttk_widget_style(
self, style, **kwargs
)
elif bootstyle:
ttkstyle = Bootstyle.update_ttk_widget_style(
self, bootstyle, **kwargs
)
kwargs.update(style=ttkstyle)
# update widget configuration
func(self, cnf, **kwargs)
return configure
override_ttk_widget_constructor(func)
staticmethod
Override widget constructors with bootstyle api options.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
func |
Callable |
The widget class |
required |
Source code in ttkbootstrap/style.py
@staticmethod
def override_ttk_widget_constructor(func):
"""Override widget constructors with bootstyle api options.
Parameters:
func (Callable):
The widget class `__init__` method
"""
def __init__(self, *args, **kwargs):
# capture bootstyle and style arguments
if "bootstyle" in kwargs:
bootstyle = kwargs.pop("bootstyle")
else:
bootstyle = ""
if "style" in kwargs:
style = kwargs.pop("style") or ""
else:
style = ""
# instantiate the widget
func(self, *args, **kwargs)
# must be called AFTER instantiation in order to use winfo_class
# in the `get_ttkstyle_name` method
if style:
if Style.get_instance().style_exists_in_theme(style):
self.configure(style=style)
else:
ttkstyle = Bootstyle.update_ttk_widget_style(
self, style, **kwargs
)
self.configure(style=ttkstyle)
elif bootstyle:
ttkstyle = Bootstyle.update_ttk_widget_style(
self, bootstyle, **kwargs
)
self.configure(style=ttkstyle)
else:
ttkstyle = Bootstyle.update_ttk_widget_style(
self, "default", **kwargs
)
self.configure(style=ttkstyle)
return __init__
setup_ttkbootstap_api()
staticmethod
Setup ttkbootstrap for use with tkinter and ttk. This method is called when ttkbootstrap is imported to perform all of the necessary method overrides that implement the bootstyle api.
Source code in ttkbootstrap/style.py
@staticmethod
def setup_ttkbootstap_api():
"""Setup ttkbootstrap for use with tkinter and ttk. This method
is called when ttkbootstrap is imported to perform all of the
necessary method overrides that implement the bootstyle api."""
from ttkbootstrap.widgets import TTK_WIDGETS
from ttkbootstrap.widgets import TK_WIDGETS
# TTK WIDGETS
for widget in TTK_WIDGETS:
try:
# override widget constructor
_init = Bootstyle.override_ttk_widget_constructor(
widget.__init__
)
widget.__init__ = _init
# override configure method
_configure = Bootstyle.override_ttk_widget_configure(
widget.configure
)
widget.configure = _configure
widget.config = widget.configure
# override get and set methods
_orig_getitem = widget.__getitem
_orig_setitem = widget.__setitem
def __setitem(self, key, val):
if key in ("bootstyle", "style"):
return _configure(self, **{key: val})
return _orig_setitem(key, val)
def __getitem(self, key):
if key in ("bootstyle", "style"):
return _configure(self, cnf=key)
return _orig_getitem(key)
if (
widget.__name__ != "OptionMenu"
): # this has it's own override
widget.__setitem__ = __setitem
widget.__getitem__ = __getitem
except:
# this may fail in python 3.6 for ttk widgets that do not exist
# in that version.
continue
# TK WIDGETS
for widget in TK_WIDGETS:
# override widget constructor
_init = Bootstyle.override_tk_widget_constructor(widget.__init__)
widget.__init__ = _init
tkupdate_method_name(widget)
staticmethod
Lookup the tkinter style update method from the widget class
Parameters:
Name | Type | Description | Default |
---|---|---|---|
widget |
Widget |
The widget object to lookup. |
required |
Returns:
Type | Description |
---|---|
str |
The name of the method used to update the widget object. |
Source code in ttkbootstrap/style.py
@staticmethod
def tkupdate_method_name(widget):
"""Lookup the tkinter style update method from the widget class
Parameters:
widget (Widget):
The widget object to lookup.
Returns:
str:
The name of the method used to update the widget object.
"""
widget_class = Bootstyle.ttkstyle_widget_class(widget)
if widget_class:
widget_class = f"_{widget_class}"
method_name = f"update{widget_class}_style"
return method_name
ttkstyle_method_name(widget=None, string='')
staticmethod
Parse a string to build and return the name of the
StyleBuilderTTK
method that creates the ttk style for the
target widget.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
widget |
Widget |
The widget object to lookup. |
None |
string |
str |
The keyword string to parse. |
'' |
Returns:
Type | Description |
---|---|
str |
The name of the update method used to update the widget. |
Source code in ttkbootstrap/style.py
@staticmethod
def ttkstyle_method_name(widget=None, string=""):
"""Parse a string to build and return the name of the
`StyleBuilderTTK` method that creates the ttk style for the
target widget.
Parameters:
widget (Widget):
The widget object to lookup.
string (str):
The keyword string to parse.
Returns:
str:
The name of the update method used to update the widget.
"""
style_string = "".join(string).lower()
widget_type = Bootstyle.ttkstyle_widget_type(style_string)
widget_class = Bootstyle.ttkstyle_widget_class(widget, style_string)
if widget_type:
widget_type = f"_{widget_type}"
if widget_class:
widget_class = f"_{widget_class}"
if not widget_type and not widget_class:
return ""
else:
method_name = f"create{widget_type}{widget_class}_style"
return method_name
ttkstyle_name(widget=None, string='', **kwargs)
staticmethod
Parse a string to build and return a ttkstyle name.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
widget |
Widget |
The widget object. |
None |
string |
str |
A keyword string to parse. |
'' |
**kwargs |
Other keyword arguments to parse widget orientation. |
{} |
Returns:
Type | Description |
---|---|
str |
A ttk style name |
Source code in ttkbootstrap/style.py
@staticmethod
def ttkstyle_name(widget=None, string="", **kwargs):
"""Parse a string to build and return a ttkstyle name.
Parameters:
widget (Widget):
The widget object.
string (str):
A keyword string to parse.
**kwargs:
Other keyword arguments to parse widget orientation.
Returns:
str:
A ttk style name
"""
style_string = "".join(string).lower()
widget_color = Bootstyle.ttkstyle_widget_color(style_string)
widget_type = Bootstyle.ttkstyle_widget_type(style_string)
widget_orient = Bootstyle.ttkstyle_widget_orient(
widget, style_string, **kwargs
)
widget_class = Bootstyle.ttkstyle_widget_class(widget, style_string)
if widget_color:
widget_color = f"{widget_color}."
if widget_type:
widget_type = f"{widget_type.title()}."
if widget_orient:
widget_orient = f"{widget_orient.title()}."
if widget_class.startswith("t"):
widget_class = widget_class.title()
else:
widget_class = f"T{widget_class.title()}"
ttkstyle = f"{widget_color}{widget_type}{widget_orient}{widget_class}"
return ttkstyle
ttkstyle_widget_class(widget=None, string='')
staticmethod
Find and return the widget class
Parameters:
Name | Type | Description | Default |
---|---|---|---|
widget |
Widget |
The widget object. |
None |
string |
str |
A keyword string to parse. |
'' |
Returns:
Type | Description |
---|---|
str |
A widget class keyword. |
Source code in ttkbootstrap/style.py
@staticmethod
def ttkstyle_widget_class(widget=None, string=""):
"""Find and return the widget class
Parameters:
widget (Widget):
The widget object.
string (str):
A keyword string to parse.
Returns:
str:
A widget class keyword.
"""
# find widget class from string pattern
match = re.search(Keywords.CLASS_PATTERN, string.lower())
if match is not None:
widget_class = match.group(0)
return widget_class
# find widget class from tkinter/tcl method
if widget is None:
return ""
_class = widget.winfo_class()
match = re.search(Keywords.CLASS_PATTERN, _class.lower())
if match is not None:
widget_class = match.group(0)
return widget_class
else:
return ""
ttkstyle_widget_color(string)
staticmethod
Find and return widget color
Parameters:
Name | Type | Description | Default |
---|---|---|---|
string |
str |
A keyword string to parse. |
required |
Returns:
Type | Description |
---|---|
str |
A color keyword. |
Source code in ttkbootstrap/style.py
@staticmethod
def ttkstyle_widget_color(string):
"""Find and return widget color
Parameters:
string (str):
A keyword string to parse.
Returns:
str:
A color keyword.
"""
_color = re.search(Keywords.COLOR_PATTERN, string.lower())
if _color is None:
return ""
else:
widget_color = _color.group(0)
return widget_color
ttkstyle_widget_orient(widget=None, string='', **kwargs)
staticmethod
Find and return widget orient, or default orient for widget if a widget with orientation.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
widget |
Widget |
The widget object. |
None |
string |
str |
A keyword string to parse. |
'' |
**kwargs |
Optional keyword arguments passed in the widget constructor. |
{} |
Returns:
Type | Description |
---|---|
str |
A widget orientation keyword. |
Source code in ttkbootstrap/style.py
@staticmethod
def ttkstyle_widget_orient(widget=None, string="", **kwargs):
"""Find and return widget orient, or default orient for widget if
a widget with orientation.
Parameters:
widget (Widget):
The widget object.
string (str):
A keyword string to parse.
**kwargs:
Optional keyword arguments passed in the widget constructor.
Returns:
str:
A widget orientation keyword.
"""
# string method (priority)
match = re.search(Keywords.ORIENT_PATTERN, string)
widget_orient = ""
if match is not None:
widget_orient = match.group(0)
return widget_orient
# orient from kwargs
if "orient" in kwargs:
_orient = kwargs.pop("orient")
if _orient == "h":
widget_orient = "horizontal"
elif _orient == "v":
widget_orient = "vertical"
else:
widget_orient = _orient
return widget_orient
# orient from settings
if widget is None:
return widget_orient
try:
widget_orient = str(widget.cget("orient"))
except:
pass
return widget_orient
ttkstyle_widget_type(string)
staticmethod
Find and return the widget type.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
string |
str |
A keyword string to parse. |
required |
Returns:
Type | Description |
---|---|
str |
A widget type keyword. |
Source code in ttkbootstrap/style.py
@staticmethod
def ttkstyle_widget_type(string):
"""Find and return the widget type.
Parameters:
string (str):
A keyword string to parse.
Returns:
str:
A widget type keyword.
"""
match = re.search(Keywords.TYPE_PATTERN, string.lower())
if match is None:
return ""
else:
widget_type = match.group(0)
return widget_type
update_tk_widget_style(widget)
staticmethod
Lookup the widget name and call the appropriate update method
Parameters:
Name | Type | Description | Default |
---|---|---|---|
widget |
object |
The tcl/tk name given by |
required |
Source code in ttkbootstrap/style.py
@staticmethod
def update_tk_widget_style(widget):
"""Lookup the widget name and call the appropriate update
method
Parameters:
widget (object):
The tcl/tk name given by `tkinter.Widget.winfo_name()`
"""
try:
style = Style.get_instance()
method_name = Bootstyle.tkupdate_method_name(widget)
builder = style._get_builder_tk()
builder_method = getattr(StyleBuilderTK, method_name)
builder_method(builder, widget)
except:
"""Must pass here to prevent a failure when the user calls
the `Style`method BEFORE an instance of `Tk` is instantiated.
This will defer the update of the `Tk` background until the end
of the `BootStyle` object instantiation (created by the `Style`
method)"""
pass
update_ttk_widget_style(widget=None, style_string=None, **kwargs)
staticmethod
Update the ttk style or create if not existing.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
widget |
ttk.Widget |
The widget instance being updated. |
None |
style_string |
str |
The style string to evalulate. May be the |
None |
**kwargs |
Other optional keyword arguments. |
{} |
Returns:
Type | Description |
---|---|
str |
The ttkstyle or empty string if there is none. |
Source code in ttkbootstrap/style.py
@staticmethod
def update_ttk_widget_style(
widget: ttk.Widget = None, style_string: str = None, **kwargs
):
"""Update the ttk style or create if not existing.
Parameters:
widget (ttk.Widget):
The widget instance being updated.
style_string (str):
The style string to evalulate. May be the `style`, `ttkstyle`
or `bootstyle` argument depending on the context and scenario.
**kwargs:
Other optional keyword arguments.
Returns:
str:
The ttkstyle or empty string if there is none.
"""
style: Style = Style.get_instance() or Style()
# get existing widget style if not provided
if style_string is None:
style_string = widget.cget("style")
# do nothing if the style has not been set
if not style_string:
return ""
if style_string == '.':
return '.'
# build style if not existing (example: theme changed)
ttkstyle = Bootstyle.ttkstyle_name(widget, style_string, **kwargs)
if not style.style_exists_in_theme(ttkstyle):
widget_color = Bootstyle.ttkstyle_widget_color(ttkstyle)
method_name = Bootstyle.ttkstyle_method_name(widget, ttkstyle)
builder: StyleBuilderTTK = style._get_builder()
builder_method = builder.name_to_method(method_name)
builder_method(builder, widget_color)
# subscribe popdown style to theme changes
try:
if widget.winfo_class() == "TCombobox":
builder: StyleBuilderTTK = style._get_builder()
winfo_id = hex(widget.winfo_id())
winfo_pathname = widget.winfo_pathname(winfo_id)
Publisher.subscribe(
name=winfo_pathname,
func=lambda w=widget: builder.update_combobox_popdown_style(
w
),
channel=Channel.STD,
)
builder.update_combobox_popdown_style(widget)
except:
pass
return ttkstyle