Modern Tkinter
This tutorial will quickly get you up and running with the latest Tk from Python, Tcl, Ruby, and Perl on macOS, Windows, or Linux. It provides all the essentials about core Tk concepts, the various widgets, layout, events and more that you need for your application.

Fonts, Colors, Images

This chapter describes how Tk handles fonts, colors, and images. We've touched on all of these before, but here we'll provide a more in-depth treatment.

Fonts

Tk's label widget allows you to change the font used to display text via the font configuration option. The canvas and text widgets, covered in the following chapters, also allow you to specify fonts. Other themed widgets that display text may not have a font configuration option, but their fonts can be changed using styles.

We'll cover styles in detail later. In essence, they replace the old way of tweaking multiple configuration options on individual widgets. Instead, fonts, colors, and other settings that control appearance can be bundled together in a style. That style can then be applied to multiple widgets. It's akin to the difference between hardcoding display-oriented markup inside HTML pages vs. using CSS to keep display-specific information separate.

As with many things in Tk, the default fonts are usually a good choice. If you need to make changes, this section shows you the best way to do so, using named fonts. Tk includes named fonts suitable for use in all different components of your user interface. They take into account the conventions of the specific platform you're running on. You can also specify your own fonts when you need additional flexibility.

The font command reference provides full details on specifying fonts, as well as other font-related operations.

Many older Tk programs hardcoded fonts, using either the "family size style" format we'll see below, X11 font names, or the older and more arcane X11 font specification strings. These applications looked increasingly dated as platforms evolved. Worse, fonts were often specified on a per-widget basis, leaving font decisions spread throughout the code. Named fonts, particularly the standard fonts that Tk provides, are a far better solution. Reviewing and updating font decisions is an easy and important change to make in any existing application.

Standard Fonts

Each platform defines specific fonts that should be used for standard user interface elements. Tk encapsulates many of these decisions into a standard set of named fonts. They are available on all platforms, though the exact font used will vary. This helps abstract away platform differences. Of course, the standard widgets use these named fonts. The predefined fonts are:

TkDefaultFont:
Default for items not otherwise specified.
TkTextFont:
Used for entry widgets, listboxes, etc.
TkFixedFont:
A standard fixed-width font.
TkMenuFont:
The font used for menu items.
TkHeadingFont:
Font for column headings in lists and tables.
TkCaptionFont:
A font for window and dialog caption bars.
TkSmallCaptionFont:
A smaller caption font for tool dialogs.
TkIconFont:
A font for icon captions.
TkTooltipFont:
A font for tooltips.

Platform-Specific Fonts

Tk provides additional named fonts to help you comply with less common situations on specific platforms. Individual platform guidelines detail how and where these fonts should be used. These fonts are only defined on specific platforms. You'll need to take that into account if your application is portable across platforms.

Tk on X11 recognizes any valid X11 font name (see, e.g., the xlsfonts command). However, these can vary with the operating system, installed software, and the configuration of the individual machine. There is no guarantee that a font available on your X11 system has been installed on any other X11 system.

On Windows, Tk provides named fonts for all the fonts that can be set in the "Display" Control Panel. It recognizes the following font names: system, ansi, device, systemfixed, ansifixed, and oemfixed.

On macOS, the Apple Human Interface Guidelines (HIG) specifies a number of additional fonts. Tk recognizes the following names: systemSystemFont, systemSmallSystemFont, systemApplicationFont, systemViewsFont, systemMenuItemFont, systemMenuItemCmdKeyFont, systemPushButtonFont, systemAlertHeaderFont, systemMiniSystemFont, systemDetailEmphasizedSystemFont, systemEmphasizedSystemFont, systemSmallEmphasizedSystemFont, systemLabelFont, systemMenuTitleFont, systemMenuItemMarkFont, systemWindowTitleFont, systemUtilityWindowTitleFont, systemToolbarFont, and systemDetailSystemFont.

Working with Named Fonts

Tk provides several operations that help you work with named fonts. You can start by getting a list of all the currently defined named fonts.

from tkinter import font
font.names()
font names
TkFont.names
Tkx::font_names()

You can find out the actual system font represented by an abstract named font. This consists of the family (e.g., Times or Helvetica), the size (in points if positive, in pixels if negative), the weight (normal or bold), the slant (roman or italic), and boolean attributes for underline and overstrike. You can find out the font's metrics (how tall characters in the font can be and whether it is monospaced), and even measure how many pixels wide a piece of text rendered in the font would be.

>>> from tkinter import font
>>> f = font.nametofont('TkTextFont')
>>> f.actual()
{'family': '.AppleSystemUIFont', 'size': 13, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0}
>>> f.metrics()
{'ascent': 13, 'descent': 3, 'linespace': 16, 'fixed': 0}
>>> f.measure('The quick brown fox')
124

Tkinter provides a Font class to hold information about a named font. You can create an instance of this class from the name of a font using the nametofont function. When you use named fonts in your application (e.g., via a label's font configuration option), you can supply either the font name (as a string) or a Font instance.

% font actual TkTextFont
-family .AppleSystemUIFont -size 13 -weight normal -slant roman -underline 0 -overstrike 0
% font metrics TkTextFont
-ascent 13 -descent 3 -linespace 16 -fixed 0
% font measure TkTextFont "The quick brown fox"
124
irb(main):003:0> TkFont.actual "TkTextFont"
=> [["family", ".AppleSystemUIFont"], ["size", 13], ["weight", "normal"], ["slant", "roman"], ["underline", false], ["overstrike", false]]
irb(main):004:0> TkFont.metrics "TkTextFont"
=> [["ascent", 13], ["descent", 3], ["linespace", 16], ["fixed", 0]]
irb(main):005:0> TkFont.measure "TkTextFont", "The quick brown fox"
=> 124
perl> Tkx::font_actual('TkTextFont')
-family .AppleSystemUIFont -size 13 -weight normal -slant roman -underline 0 -overstrike 0
perl> Tkx::font_metrics('TkTextFont')
-ascent 13 -descent 3 -linespace 16 -fixed 0
perl> Tkx::font_measure('TkTextFont', 'The quick brown fox')
124

Trying these in an interactive shell and got an error? Even though we're not displaying anything onscreen, you need to initialize Tk before using the various font functions.

You can also create your own fonts, which can then be used exactly like the predefined ones. To do so, choose a name for the font and specify its font attributes as above.

from tkinter import font
highlightFont = font.Font(family='Helvetica', name='appHighlightFont', size=12, weight='bold')
ttk.Label(root, text='Attention!', font=highlightFont).grid()

If you don't supply a name, Tkinter will generate one, which you can retrieve via font.name or str(font). It's usually best to supply one.

font create AppHighlightFont -family Helvetica -size 12 -weight bold
grid [ttk::label .l -text "Attention!" -font AppHighlightFont]
AppHighlightFont = TkFont.new :family => 'Helvetica', :size => 12, :weight => 'bold'
Tk::Tile::Label.new(root) {text 'Attention!'; font AppHighlightFont}.grid
Tkx::font_create("AppHighlightFont", -family => "Helvetica", -size => 12, -weight => "bold");
$l = $parent->new_ttk__label(-text => "Attention!", -font => "AppHighlightFont");
$l->g_grid;

The family attribute specifies the font family. Tk ensures the names Courier, Times, and Helvetica are available, though they may be mapped to an appropriate monospaced, serif, or sans-serif font). Other fonts installed on your system can be used, but the usual caveats about portability apply. You can get the names of all available families with:

font.families()
font families
TkFont.families
Tkx::font_families()

You can change the attributes of a named font using its configure method. You might do this in response to menu options allowing users to zoom in or out, i.e., increasing or decreasing font sizes.

Font Descriptions

Another way to specify fonts is via a list of attributes, starting with the font family, and optionally including a size and one or more style options. Some examples of this are Helvetica, Helvetica 12, Helvetica 12 bold, and Helvetica 12 bold italic. These font descriptions can be used anywhere you'd use a named font, e.g., a font configuration option.

In general, switching from font descriptions to named fonts is advisable to isolate font differences in one location in the program.

Colors

As with fonts, there are various ways to specify colors. Full details can be found in the colors command reference.

In general, Tk widgets default to the right colors for most situations. If you'd like to change colors, you'll do so via widget-specific commands or options, e.g., the label's foreground and background configuration options. For most themed widgets, color changes are specified through styles, not by changing the widget directly.

You can specify colors via RGB, as you would in HTML or CSS, e.g. #3FF or #FF016A. Tk also recognizes names such as red, black, grey50, light blue, etc.

Tk recognizes the standard names for colors defined by X11. You can find a complete list in the command reference (noted above).

As with fonts, both macOS and Windows specify many system-specific abstract color names (again, see the reference). The actual color these correspond to may depend on system settings and can change over time, e.g., dark mode, text highlight colors, default backgrounds.

If needed, you can find the RGB values (each between 0 and 65535) for a color using the winfo_rgb method on any widget.

root.winfo_rgb('red')
winfo rgb . red
root.winfo_rgb('red')
$mw->g_winfo_rgb('red')

It should probably go without saying, but restraint in the use of colors is highly advisable!

Images

We've seen the basics of using images already, displaying them in labels or buttons, for example. We create an image object, usually from a file on disk.

imgobj = PhotoImage(file='myimage.gif')
label['image'] = imgobj
image create photo imgobj -file "myimage.gif"
.label configure -image imgobj
image = TkPhotoImage.new(:file => "myimage.gif")
label['image'] = image
Tkx::image_create_photo("imgobj", -file => "myimage.gif");
$l->configure(-image => "imgobj");

Out of the box, Tk 8.5 includes support for GIF and PPM/PNM images. Tk 8.6 added PNG to this short list. However, a Tk extension library called Img adds support for many others: BMP, XBM, XPM, JPEG, PNG (if you're using 8.5), TIFF, etc. Though not included directly in the Tk core, Img is usually included with other packaged distributions (e.g., ActiveTcl).

Instead of using Tk's Img extension, Tkinter uses a made-for-Python image library called PIL (Python Imaging Library). More specifically, we'll use a more up-to-date fork of PIL called pillow. As it doesn't come bundled with Python, you'll normally need to install it. You should be able to do so via, e.g., pip install Pillow.

from PIL import ImageTk, Image
myimg = ImageTk.PhotoImage(Image.open('myimage.png'))

The ImageTk.PhotoImage call provides a drop-in replacement for Tk's PhotoImage but supports the broader range of image types.

package require Img
image create photo myimg -file "myimage.png"
require 'tkextlib/tkimg'
myimg = TkPhotoImage.new(:file => 'myimage.png')
Tkx::package_require("Img");
Tkx::image_create_photo("myimg", -file => "myimage.png");

Tk's images are actually quite powerful and sophisticated and provide various ways to inspect and modify images. You can find out more from the image command reference and the photo command reference.

The types of multi-color images we've seen here are referred to in Tk as photo images. Tk also provides a second type, two-bit bitmap images, which were widely used in the '90s when most Unix workstations used quite large (compared with PCs) monitors, but they were only black and white. Needless to say, color is mostly de rigueur these days, so updating to full-color images for icons and so on is highly advisable. Though in what some may consider retro-styling, some flat and material design schemes have returned to black and white. Plus ça change...