Up to this point we have used tkinter widgets. For every widget, we had to set all the attributes. We could have this on off panel of three buttons and a label:
#TTK first example #traditional tkinter for basis from tkinter import * #from tkinter import ttk #make the window root=Tk() root.title('TTK Power Panel #1') #make the frame frame = Frame(root) frame.grid(row=0, column=0) #variables status =StringVar() #Styles #controller def onButtonPressed(): status.set('On') def offButtonPressed(): status.set('Off') #view #label status.set('System Off') status_label = Label(frame, textvariable = status) status_label.configure(font=('Sans','14','bold'),background = 'blue', foreground = '#eeeeff') status_label.grid(row=0,column=0,columnspan=3,sticky=EW) #on Button on_button = Button(frame, command = onButtonPressed, text = 'On') on_button.configure(font=('Sans','14','bold'),background = 'blue', foreground = '#eeeeff') on_button.grid(row = 2, column = 0) #off Button off_button = Button(frame, command = offButtonPressed, text = 'Off') off_button.configure(font=('Sans','14','bold'),background = 'blue', foreground = '#eeeeff') off_button.grid(row = 2, column = 1) quit_button = Button(frame, command = quit, text = 'Quit') quit_button.configure(font=('Sans','14','bold'),background = 'blue', foreground = '#eeeeff') quit_button.grid(row = 2, column = 2) #main loop mainloop()
Type it in, save and run.
Each button uses the same .configure()
for every widget:
.configure(font=('Sans','14','bold'),background = 'blue', foreground = '#eeeeff')
While we have only three buttons, this can get tedious when there are many buttons. The application would be simpler to code and more consistent in its styling if there was a way to code for all of these. Later versions of tkinter does has such a feature. Tkinter introduced ttk-themed widgets to create one set of styles for all the widgets, or for certain types of widgets.
To use this, we need to import a special part of tkinter called ttk.
Change the from..import
to this:
from tkinter import * from tkinter import ttk
Change the on_button
to this:
on_button = ttk.Button(frame, command = onButtonPressed, text = 'On')
Change the off_button
to this:
off_button = ttk.Button(frame, command = offButtonPressed, text = 'Off')
Change the quit_button
to this:
quit_button = Button(frame, command = quit, text = 'Quit')
Save and run. You will get syntax errors.
_tkinter.TclError: unknown option "-font"
The font
option suddenly is no longer recognized. The ttk-themed widgets do not directly use font
, foreground
or background
. They are all moved to a style sheet.
Comment out the three .configure()
lines for the buttons:
#on_button.configure(font=('Sans','14','bold'),background = 'blue', foreground = '#eeeeff') #off_button.configure(font=('Sans','14','bold'),background = 'blue', foreground = '#eeeeff') #quit_button.configure(font=('Sans','14','bold'),background = 'blue', foreground = '#eeeeff')
Add the following just below the #Styles
comment:
s = ttk.Style() s.configure('TButton',background = 'blue', foreground = '#ddddff', font = ('Sans','14','bold'), relief = FLAT)
Run this and you will get all three buttons looking the same.
The first parameter is the type of widget, confusingly called a widget class. It is not a Python class, but a type of widget. Most of the widget classes prefix a capital T to the name of the widget. The rest of the parameters is the attributes, just like we configured them with a .configure()
for non-themed widgets.
Try placing the mouse pointer over a button, and we have a problem.
The button highlights, and the text is unreadable. In our earlier lessons, we would use activebackground
, and activeforeground
to control this. However in ttk themed widgets, those do not exist. Instead a series of states can exist for the widget. One such state is active
For each state, we map an attribute different from the default set in .configure()
. To do this use the .map()
method. To change the text color to black we can do this:
s.map('TButton',foreground = [('active','black')] )
Add this to your code under the s.configure()
line. While configure took straight assignments for the attributes, .map()
is a bit more complicated. Each attribute takes a list, denoted by the square brackets. The list has tuples of two strings with the form (state,attribute)
. Run this code.
The button changes the text color when we hover over it. We can do the same for the background color. Add below the last .map()
method the following:
s.map('TButton', background = [('active','#aaaaff')])
Save and run.
When the mouse hovers or the button changes background color. This is the very basic use of the ttk themed widgets, but enough to get started. We’ll look at bit more into them in further lessons.
Leave a Reply