States and Themes#
Script 03states_themes.py#
Show/Hide Code 03states_themes.py
"""
Ttk Theme Selector and State.
Although it is a theme selector, you won't notice many changes since
there are only radiobuttons, a frame around and the selected widget.
The state selector only applies to the selected widget.
"""
from tkinter import StringVar, Tk
from tkinter.ttk import Frame, Style, Button, Radiobutton, Label
class App:
def __init__(self,root):
self.fr = Frame(root)
self.fr.pack(fill='both', expand=1)
## uncomment following 5 lines if using ttkthemes
'''
try:
import ttkthemes as ts
self.style = ts.themed_style.ThemedStyle()
except (NameError, AttributeError):
self.style = Style()
'''
self.style = Style() ## comment out if using ttkthemes
self._setup_widgets()
def _change_theme(self):
newtheme = self.theme_val.get()
self.style.theme_use(newtheme)
def _change_state(self):
oldstate = self.but.state()
if len(oldstate) > 0:
# convert tuple to string
oldst = " ".join(str(x) for x in oldstate)
self.but.state(['!'+oldst])
newstate = self.state_val.get()
self.but.state([newstate])
def _setup_widgets(self):
l = Label(self.fr, text="Dont't forget click and hover, \n \
or see more by using the radio buttons")
l.grid(column=0,row=0,columnspan=3,padx=5,pady=2, sticky='n')
themes = sorted(list(self.style.theme_names()))
# Create rasio buttons which will display themes
self.theme_val = StringVar()
for ix, val in enumerate(themes):
themes_rb = Radiobutton(self.fr, value=val, text=val,
variable=self.theme_val, command=self._change_theme)
themes_rb.grid(column=0,row=ix+1,padx=5,pady=2, sticky='nw')
states = ['active', 'alternate', 'background', 'disabled',
'focus', 'invalid', 'pressed', 'readonly', 'selected']
# Create rasio buttons which will display widget states
self.state_val = StringVar()
for iy, state in enumerate(states):
st_rb = Radiobutton(self.fr, value=state, text=state,
variable=self.state_val, command=self._change_state)
st_rb.grid(column=1,row=iy+1,padx=5,pady=5, sticky='nw')
# selected widget, if using scrollbar place in own frame
self.but = Button(self.fr, text='Button State')
self.but.grid(column=3,row=ix+2,padx=5,pady=5)
if __name__ == "__main__":
Root = Tk()
Root.title("Ttk Theme and State Selector")
app = App(Root)
Root.mainloop()
there is no problem changing themes, however when changing states we need to cancel the previous state by applying the opposite state (you remember the state prefixed with an exclamion mark), we also have to ensure that we are dealing with a string rather than a tuple, further we must ensure that the tuple is not empty. In our example we are changing the state of a button, you can modify this or add another widget as required.
As we have already seen states are not only used singly, they may be used in combination, particularly in dynamic situations. The common themes do not always use the same states for any particular widget, if we are building custom widgets keep this in mind, as ever test using different themes. Check out the table 03mapped_states.csv to see the states that the themes use with which widget.
Show/Hide Table 03mapped_states.csv
Widget |
Class Name |
mapped states alt |
mapped states clam |
mapped states classic |
mapped states default |
|---|---|---|---|---|---|
Common |
. |
disabled, active |
disabled, active, focus |
disabled, active, focus disabled, active |
|
Button |
TButton |
{pressed !disabled}, {active !disabled}, alternate |
disabled, pressed, active, alternate {!disabled pressed} |
{!disabled pressed} |
|
Checkbutton |
TCheckbutton |
disabled, pressed |
disabled, pressed |
pressed, selected |
pressed, selected |
Combobox |
TCombobox |
readonly, disabled |
active, pressed, {readonly focus} |
readonly, disabled |
readonly, disabled |
Entry |
TEntry |
readonly, disabled |
readonly, focus |
readonly, disabled |
readonly, disabled |
Notebook |
TNotebook.Tab |
selected |
selected |
selected |
selected |
Radiobutton |
TRadiobutton |
disabled, pressed |
disabled, pressed |
pressed, selected |
pressed, selected |
Scale |
TScale |
{pressed !disabled} |
|||
Scrollbar |
TScrollbar |
{pressed !disabled} |
disabled |
||
Spinbox |
TSpinbox |
readonly, disabled |
readonly, disabled |
readonly, disabled |
readonly, disabled |
Treeview |
Treeview |
selected |
selected |
selected |
selected |