3. Themes and Styling (witkets.Style)

This class extends ttk.Style to provide an alternate fashion of defining styles. They are read from INI-like files or strings.

3.1. Usage options

There are four approaches for the style definitions:

  1. put the style definitions inside TkBuilder’s <style> tag

    <root borderwidth="15">
        <style>
            [Error.TLabel]
                foreground=red
                font=Helvetica 12 bold
        </style>
        <label wid="label1" text="This is an error!" style="Error.TLabel">
        <geometry>
            <pack for="label1">
        </geometry>
    </root>
    
  2. use an external INI file and load it with Python

    >>> import witkets as wtk
    >>> # ...
    >>> style = wtk.Style()
    >>> style.apply_from_file('styles.ini')
    
  3. use an external INI file and reference it inside the <style> tag

    <root borderwidth="15">
        <!-- Path relative to Python's working directory -->
        <style fromfile='styles.ini' />
        <label wid="label1" text="This is an error!" style="Error.TLabel">
        <geometry>
            <pack for="label1">
        </geometry>
    </root>
    
  4. load a string directly with Python

    >>> import witkets as wtk
    >>> # ...
    >>> MY_STYLE = '''
    ... [Red.TLabel]
    ... foreground=red
    ... '''
    >>> style = wtk.Style()
    >>> style.apply_from_string(MY_STYLE)
    

3.2. Format

The format is quite simple: INI sections names represents ttk style names. Style values are passed as INI key–values. The example below shows a basic stylesheet:

styles3a.ini

[TButton]
relief=raised
borderwidth=1
background=#008
foreground=#FFF
highlightbackground=#008
foreground.active._pressed = #ccd900
foreground.disabled = #555
foreground.pressed = #ff4e00
background.active._pressed = #00A
background.pressed = #008
background.disabled = #CCC
relief.pressed = ridge
relief._pressed = groove

[BigButton.TButton]
font=Helvetica 36 bold
foreground=#000
background=#DDC
borderwidth=0
relief=flat

In this simple case, most buttons will have a blue background (color #008) except the ones having the style prefix BigButton (color #DDC). On MS Windows platforms, some native widgets are used and impose some limitations. Some of the customizations, notably buttons background, are ignored. For workarounds, follow the example on the MS Windows section.

Composed styles are used to deal with particular widget states and are described with the ‘.’ character acting as a separator. This is shown in the in the fragment below.

styles3b.ini (modified TButton definition)

[TButton]
relief=raised
borderwidth=1
background=#008
foreground=#FFF
highlightbackground=#008
foreground.active._pressed = #ccd900
foreground.disabled = #555
foreground.pressed = #ff4e00
background.active._pressed = #00A
background.pressed = #008
background.disabled = #CCC
relief.pressed = ridge
relief._pressed = groove

[BigButton.TButton]
font=Helvetica 36 bold
foreground=#000
background=#DDC
borderwidth=0
relief=flat

Please refer to tkinter.ttk documentation or this tutorial <http://www.tkdocs.com/tutorial/styles.html> for a detailed explanation on widget style classes and attributes.

3.3. Example

The snippet below should test the stylesheet provided in the last section:

demo3.py

import tkinter as tk
import tkinter.ttk as ttk
import witkets as wtk

root = tk.Tk()
s = wtk.Style()
wtk.Style.set_default_fonts()
s.apply_default()                  # applying default theme first
s.theme_use('clam')
s.apply_from_file('styles3b.ini')  # override buttons and create style class

ttk.Button(root, text='normal').pack(side=tk.LEFT)
b = ttk.Button(root, text='BIG One!')
b['style'] = 'BigButton.TButton'
b.pack(side=tk.LEFT, expand='1')

root.mainloop()

The static method Style.set_default_fonts() normalizes Tk fonts to Helvetica 11. The rendered window is shown in the following figure.

_images/theme_screenshot.png

Blue buttons – witkets.Style in action

3.4. The Default Theme

A default stylesheet is provided and can be used by calling the method apply_default().

Also, its contents can be retrieved by importing the pkgutil module and then accessing the data file with pkgutil.get_data('witkets', 'data/default_theme.ini'). However, to be able to override some rules, it is sufficient to read a stylesheet with the desired modifications, normally after applying the default theme.

Once the witkets package is installed, one can see the default theme style definitions by running the demo application:

python3 -m witkets.scripts.demo

3.4.1. Labels styles screenshot

_images/default-theme-labels.png

3.4.2. Entries styles screenshot

_images/default-theme-entries.png

3.4.3. Buttons styles screenshot

_images/default-theme-buttons.png

3.4.4. Frames styles screenshot

_images/default-theme-frames.png

3.4.5. New styles

The following styles are provided:

  • Labels and Messages
    • Header.TLabel

    • Error.TLabel

    • Success.TLabel

    • Header.TMessage

    • Error.TMessage

    • Success.TMessage

  • Entries
    • Invalid.TEntry

    • Incomplete.TEntry

  • Buttons
    • Primary.TButton

    • Cancel.TButton

  • Frames
    • Bordered.TFrame

  • Witkets
    • MenuEntry.TLabel (AccelLabel widget)

    • Accelerator.TLabel (AccelLabel widget)

    • Expander.TButton

    • Ribbon.TButton

    • Ribbon.TLabel

    • Ribbon.TNotebook

    • Ribbon.TNotebook.Tab

    • Ribbon.TFrame

    • RibbonBottom.TLabel

    • RibbonBottom.TFrame

    • RibbonBottom.TButton

    • RibbonGroupInner.TFrame

    • RibbonGroup.TFrame

    • ThemedLabelFrame.TFrame

    • ThemedLabelFrame.TLabel

    • Toolbar.TFrame

    • Toolbar.TButton

Some new widgets provided by this package, notably ThemedLabelFrame, Expander and Toolbar, depends on styles defined by the default theme.

3.5. MS Windows-specific considerations

Be aware of a ttk limitation on MS Windows platform preventing changes on the background color of ttk.Button instances when native widgets are used. To properly change the button background on MS Windows, you might want to call the theme_use() method before applying your custom styles.

>>> import tkinter as tk
>>> import tkinter.ttk as ttk
>>> import witkets as wtk
>>> root = tk.Tk()
>>> style = wtk.Style()
>>> style.theme_use('clam') # choose one of the available themes
>>> style.apply_from_file('styles3b.ini')
>>> button = ttk.Button()
>>> button.pack()
>>> root.mainloop()

3.6. API Reference

class witkets.style.Style(master=None)

Look-and-feel management

Parameters

master – Master widget related to this ttk Style object or None for root

__init__(master=None)
apply_default()

Read and apply the witkets package default theme

apply_from_file(filepath)

Read styles defined in filepath (INI file)

apply_from_string(rules)

Read styles defined in string rules (INI string)

introspect(layout)

Returns a list of available properties for a given layout.

Example

>>> import witkets as wtk
>>> style = wtk.Style()
>>> style.introspect('TLabel')
static set_default_fonts()

Set Tk fonts to witkets default (Helvetica 11)