Next / Previous / Contents

50.2. ttk style maps: dynamic appearance changes

The ttk widgets can change their appearance during the execution of the program. For example, when a widget is disabled, it will not respond to mouse or keyboard actions. Typically a disabled widget presents a different appearance so that the user might realize that the widget will not respond to the mouse.

In general, every ttk widget has a set of state flags that you can use to make the appearance of a widget change during execution. Each state may be set (turned on) or reset (turned off) independently of the other states. The states and their meanings:

active The mouse is currently within the widget.
alternate This state is reserved for application use.
background Under Windows or MacOS, the widget is located in a window that is not the foreground window.
disabled The widget will not respond to user actions.
focus The widget currently has focus.
invalid The contents of the widget are not currently valid.
pressed The widget is currently being pressed (e.g., a button that is being clicked).
readonly The widget will not allow any user actions to change its current value. For example, a read-only Entry widget will not allow editing of its content.
selected The widget is selected. Examples are checkbuttons and radiobuttons that are in the “on” state.

Some states will change in response to user actions, for example, the pressed state of a Button. Your program can interrogate, clear, or set any state by using functions described in Section 46, “Methods common to all ttk widgets”.

The logic that changes the appearance of a widget is tied to one of its elements. To interrogate or set up dynamic behavior for a specific style, given an instance s of ttk.Style, use this method, where styleName is the element's name, e.g., 'Button.label' or 'border'.

    s.map(styleName, *p, **kw)

To determine the dynamic behavior of one option of a given style element, pass the option name as the second positional argument, and the method will return a list of state change specifications.

Each state change specification is a sequence (s0, s1, n). This sequence means that when the widget's current state matches all the si parts, set the option to the value n. Each item si is either a state name, or a state name preceded by a “!”. To match, the widget must be in all the states described by items that don't start with “!”, and it must not be in any of the states that start with “!”.

For example, suppose you have an instance s of class ttk.Style, and you call it like this:

    changes = s.map('TCheckbutton', 'indicatorcolor')

Further suppose that the return value is:

[('pressed', '#ececec'), ('selected', '#4a6984')]

This means that when a checkbutton is in the pressed state, its indicatorcolor option should be set to the color '#ececec', and when the checkbutton is in the selected state, its indicatorcolor option should be set to '#4a6984'.

You may also change the dynamic behavior of an element by passing one or more keyword arguments to the .map() method. For example, to get the behavior of the above example, use this method call:

    s.map('TCheckbutton',
        indicatoron=[('pressed', '#ececec'), ('selected', '#4a6984')])

Here's a more complex example. Suppose you want to create a custom button style based on the standard TButton class. We'll name our style Wild.TButton; because our name ends with “.TButton”, it automatically inherits the standard style features. Here's how to set up this new style:

    s = ttk.Style()
    s.configure('Wild.TButton',
        background='black',
        foreground='white',
        highlightthickness='20',
        font=('Helvetica', 18, 'bold'))
    s.map('Wild.TButton',
        foreground=[('disabled', 'yellow'),
                    ('pressed', 'red'),
                    ('active', 'blue')],
        background=[('disabled', 'magenta'),
                    ('pressed', '!focus', 'cyan'),
                    ('active', 'green')],
        highlightcolor=[('focus', 'green'),
                        ('!focus', 'red')],
        relief=[('pressed', 'groove'),
                ('!pressed', 'ridge')])
  • This button will initially show white text on a black background, with a 20-pixel-wide focus highlight.

  • If the button is in 'disabled' state, it will show yellow text on a magenta background.

  • If the button is currently being pressed, the text will be red; provided the button does not have focus, the background will be cyan. The tuple ('pressed', '!focus', 'cyan') is an example of how you can make an attribute dependent on a combination of states.

  • If the button is active (under the cursor), the text will be blue on a green background.

  • The focus highlight will be green when the button has focus and red when it does not.

  • The button will show ridge relief when it is not being pressed, and groove relief when it is being pressed.