Version 2 of a demo of THEMES for Tk GUI's, using images and colors

uniquename - 2012nov08

On the page Experiments with flexible THEMES for Tk GUI's, using images and colors, I presented images from and code for a demo Tk script that shows a way of creating 'themes' (composed of images and colors) for Tk GUI's.

I pointed out a couple of 'looks' that I would like to improve:

  • the look of the label to the left of the 'scale' widget
  • the look of the radiobuttons and checkbuttons

Here is one of the demo images for reference.

tkThemesDemoGUI_blue_screenshot_579x464.jpg

More specifically:

For the label to the left of the 'scale' widget, I wanted to find a 'fill-y' technique of some sort --- to make the label (that is, its underlying image) expand in the y-direction --- in order to cover some of the plain-color area, above and below the label, with a shaded image that matches the 'theme'.

And for the radiobuttons and checkbuttons, it would be nice if we could get the image under the text to extend under the 'indicators' --- the 'radiobutton-circles' and the 'checkbutton-square'.


Well, after quite a bit of frustrating coding and testing and re-coding, I found a 'technique' for the former and a 'work-around' for the latter --- and here is an image showing the result.

tkThemesDemoGUI_VERSION2_blue_screenshot_647x422.jpg

You can compare this image with the one above.

Perhaps there are many who would not agree, but I think the 2nd image is a pretty good improvement over the first one.


The 'technique' - for the label to the left of the scale :

The 'trick' to getting the image to expand in the y-direction (under the label for the scale) was to double the height in the '-height' parameter for that image and, at the same time, use a '-zoom 2' parameter. That proved to be a pretty simple solution.


The 'workaround' - for the radio/check-button 'indicators' :

Getting the image under the text on the radio/check-button to 'extend' under the 'indicators' proved to be a much thornier problem.

To make a long story relatively short, the '-compound center' option was the problem. It is the only way we have to put an image on the background of radio/check-buttons, BUT it always wants to CENTER the text on the image. There is no way to adjust the position of the text on the image.

So I was forced to a workaround: implement each radio/check-button as TWO widgets --- a radio/check-button and a label --- with appropriate padding in packing the widgets (to separate the pairs), and with use of the '-highlightthickness 0' option to get each pair to fit together seamlessly.

There was an additional bit of 'trickery' involved: To get the radio/check-button 'indicators' to show, I had to use the parameters '-width 1' and '-anchor w' when defining those widgets.

If I did not use '-anchor w', the long button image was centered in a small rectangle with the 'indicator' off to the left, out of sight.

And if I used '-width 0', the entire long-button image showed.

If I used '-width 10', the indicator WAS on top of a clipped image of the long button, BUT the indicator was not centered in a clipped rectangle of the image --- there seemed to be 10 extra pixels on the right. (This was before I discovered the '-highlightthickness 0' option/trick, to seamlessly weld together the label and the radio/check-button.)

Apparently, Tk/wish allows space/width for the 'indicator' and any space requested via the '-width' option is added to that initial width allocation. So I supplied the minimal width that I could --- '-width 1', and the extra pixel on the right is not noticeable --- especially after 'welding' the label and the radio/check-button together.


I present the code for the 'demo_tkGUI_themes_using_imagesANDcolors_VERSION2.tk' GUI-script below --- version 2 of a Tk 'themes' demo. (Version 1 is on the page Experiments with flexible THEMES for Tk GUI's, using images and colors.)

The comments at the top of the script point out that this is a GUI to demonstrate the ability to provide 'themes' for a Tk GUI --- in a quite flexible, almost-anything-is-possible way --- using a combination of images and colors.

I follow my usual 'canonical' structure for Tk code, for this Tk script:

  0) Set general window & widget parms (win-name, win-position,
     win-color-scheme, fonts, widget-geometry-parms, win-size-control,
     text-array-for-labels-etc).

  1a) Define ALL frames (and sub-frames, if any).
  1b) Pack   ALL framesand sub-frames.

  2) Define & pack all widgets in the frames, frame by frame.

  3) Define keyboard and mouse/touchpad/touch-sensitive-screen action
     BINDINGS, if needed.

  4) Define PROCS, if needed.

  5) Additional GUI initialization (typically with one or more of
     the procs), if needed.

This structure is discussed in more detail on the page A Canonical Structure for Tk Code --- and variations.

This structure makes it easy for me to find code sections --- while generating and testing a Tk script, and when looking for code snippets to include in Tk scripts (code re-use).

As I pointed out on the version 1 page, one new thing that I have added is the text-array-for-labels-etc item in section 0. This can make it easier for people to internationalize my scripts. I may be using a text-array like this in most of my scripts in the future.


As in all my scripts that use the 'pack' geometry manager (which is all of my 100-plus scripts, so far), I provide the four main pack parameters --- '-side', '-anchor', '-fill', '-expand' --- on all of the 'pack' commands for the frames and widgets.

I think I have found a pretty good setting of the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various widgets of this GUI. In particular ...

The 'canvas' and 'text' widgets expand/contract when the window size is changed --- while button and label widgets stay fixed in size and relative-location as the window size is changed.

But Tcler's can experiment with the 'pack' parameters, if they want to change the behavior of the GUI when window size is changed.

You might want to change the fonts used for the various GUI widgets. For example, you could change '-weight' from 'bold' to 'normal' --- or '-slant' from 'roman' to 'italic'. Or change font families.

In fact, you may NEED to change the font families, because the families I used may not be available on your computer --- and the default font that the 'wish' interpreter chooses may not be very pleasing.

I use variables to set geometry parameters of widgets --- parameters such as border-widths and padding. And I have included the '-relief' parameter on the definitions of frames and widgets. Feel free to experiment with those 'appearance' parameters as well.


That said, here's the code --- with plenty of comments to describe what most of the code-sections are doing.

The logic of the script gets rather 'interesting' as this is a GUI that is intended to change its own appearance. I have provided plenty of comments to help readers understand the structure and intent of various code sections. In particular, the comments are to help ME understand what I did, when I look at this in the future to get code-ideas for making enhanced Tk GUI's.

A major part of the code that is involved in setting a 'theme', according to the radiobuttons setting, is in the proc 'change_theme'.

It is my hope that the copious comments in the code will help Tcl-Tk coding 'newbies' get started in making GUI's like this. Without the comments, the code might look quite unfriendly.

Without the comments, potential young Tcler's might be tempted to return to their iPhones and iPads and iPods --- to watch LFHV (Lapland's Funniest Home Videos).


 Code for the Tk script 'demo_tkGUI_themes_using_imagesANDcolors_VERSION2.tk' :
#!/usr/bin/wish -f
##
## Tk SCRIPT NAME:   demo_tkGUI_themes_using_imagesANDcolors_VERSION2.tk
##
##+#######################################################################
## PURPOSE:  This TkGUI script provides a demo GUI that uses about 7 of the
##           commonly used Tk widgets. This is a GUI to demonstrate the ability
##           to provide 'themes' for a Tk GUI, in a quite flexible way (almost
##           anything is possible), using a combination of images and colors.
##
##           This GUI is 'self-theming' in the sense that radiobuttons
##           and a checkbutton on the GUI can be used to reconfigure
##           the GUI with different themes (combinations of 'photo'
##           images and colors).
##
##           For about 4 types of widgets (labels and 3 types of buttons),
##           the images are backgrounds for text on the widget. The text
##           is shown on top of an image via the '-compound center' option.
##
##           The widgets shown are label, button, checkbutton, radiobuttons,
##           scale, canvas, and text --- 7 widgets out of a family of
##           about 18 Tk widgets:
##
##                      button, canvas, checkbutton, entry, frame,
##                      label, labelframe, listbox, menu, menubutton,
##                      message, panedwindow, radiobutton, scale,
##                      scrollbar, spinbox, text, toplevel.
##
##           I have chosen the widgets that I use the most. I also use
##           frame, entry, and listbox widgets frequently, but they do
##           not have an '-image' option. And I seldom use an '-image'
##           option with the text widget.
##
##           Images of two types are read in:
##              - long, rectangular button shapes
##            or 
##              - large (tall and wide) rectangular background shapes.
##           The images are supplied via a GIF or PNG file.
##
##           The image is 'clipped' on each button widget (or 'copied'
##           to make a new image of the right size, for label, radiobutton,
##           and checkbutton widgets), usually according to the width
##           of the text on the widget.
##
##           The image is applied to most widgets with an '-image' option
##           and in most cases with the '-compound center' option.
##
##           The '-compound' option locates the image relative to the text
##           on the widget. Options are
##                     left,right,top,bottom,center,none.
##
##           Only 'center' and 'none' are used in this script.
##
##           (Unfortunately, there seems to be no way to locate the text
##            on the widget in a similar fashion, i.e. via compass points.
##            So one has to make do with having text centered on the
##            image. There is no option to adjust the text to the left side
##            of the underlying image, for example.)
##
##+###########
## GUI DESIGN:
##
##    The GUI includes a couple of LABEL and BUTTON widgets with different
##    lengths of text in them.
##
##    It includes a CHECKBOX widget and at least 2 RADIOBUTTON widgets.
##
##    In addition, there is a SCALE widget and a CANVAS widget.
##    A TEXT widget may also be included.
##
##    Two 'image create' commands load two GIF files into two image
##    'structures' --- for 'button' images and 'background' images ---
##    to be used on the widgets.
##
##+########################################################################
## 'CANONICAL' STRUCTURE OF THIS CODE:
##
##  0) Set general window parms (win-name,win-position,color-scheme,fonts,
##     widget-geom-parameters,win-size-control,text-array-for-labels-etc).
##  1a) Define ALL frames (and sub-frames, if any).
##  1b) Pack   ALL frames and sub-frames.
##  2) Define & pack all widgets in the frames --- going frame-by-frame.
##
##  3) Define key and mouse/touchpad/touch-sensitive-screen action
##     BINDINGS, if needed.
##  4) Define PROCS, if needed.
##  5) Additional GUI INITIALIZATION (typically with one or two procs
##     from section 4), if needed.
##
##+#################################
## Some detail on the code structure of this particular Tk script:
##
##  1a) Define ALL frames:
## 
##   Top-level : 
##       - 'fRbuttons_label' for buttons: Exit,Help
##       - 'fRlabel_scale'   for a scale for font-size
##       - 'fRradiobuttons'  for about 4 radiobuttons for color-themes
##       - 'fRcheckbuttons'  for at least one checkbutton --- to turn
##                           images off/on, for example
##       - 'fRcanvas'        for a canvas widget with a background image
##       - 'fRtext'          for a text widget with a background image
##
##  1b) Pack ALL frames.
##
##  2) Define & pack all widgets in the frames -- basically going through
##     frames & their interiors in  left-to-right and/or top-to-bottom order.
##     Only after ALL the widgets for a frame are defined, pack them.
##
##  3) Define bindings:
##       button1-release for the radiobuttons and checkbutton
##
##  4) Define procs:
##      - 'images_on_off'  - for the images off/on checkbutton
##      - 'change_theme'   - for the color-themes radiobuttons
##      - 'reset_fontsize' - for the scale widget
##      - 'popup_msg_var_scroll' - for a Help button
##
##  5) Additional GUI initialization:  set the initial values for the
##       widget variables --- for scale, checkbutton, radiobuttons ---
##       and call 'change_theme' to initialize images in the GUI.
##
##+#######################################################################
## DEVELOPED WITH: Tcl-Tk 8.5 on Ubuntu 9.10 (2009oct version, 'Karmic Koala').
##   wish> puts "$tcl_version $tk_version"
##   8.5 8.5
##+########################################################################
## FE system Copyright 2006+ by Blaise Montandon
##+########################################################################
## MAINTENANCE HISTORY:
## Started by: Blaise Montandon 2012nov04 Started development, on Ubuntu 9.10.
##                                        To develop theme-ing techniques
##                                        for use in Freedom Environment (FE)
##                                        subsystems, such as 'feHandyTools'
##                                        'feHappyScripts','feFileMan',
##                                        and 'tkGooies'.
##                                        See www.freedomenv.com
## Changed by: Blaise Montandon 2012nov07 Double the height of the label
##                                        for the scale widget. Put the
##                                        radiobutton-circles on the image
##                                        background by splitting the
##                                        text onto a separate label widget.
##                                        Similarly, put the checkbutton-square
##                                        on the image background --- using
##                                        '-width 1' and '-anchor w'.
##+#######################################################################

##+#######################################################################
## SET THE TOP WINDOW NAME.
##+#######################################################################

wm title    . "Demo - Tk Themes --- using images (under text) and colors"
wm iconname . "tkThemesDemo"


##+#######################################################################
##  SET THE TOP WINDOW POSITION.
##+#######################################################################

wm geometry . +10+20


##+#######################################################################
## SET COLOR SCHEME (palette) FOR THE WINDOW.
## (We do that in the GUI INITIALIZATION section at the bottom of
##  this script, where a choice is made of 'color-theme'.)
##+#######################################################################
## and
##+#######################################################################
## SET BACKGROUND COLOR vars FOR WIDGETS, such as
## RADIOBUTTON & CHECKBUTTON widgets.
## Also a faint (initial) foreground color for LABEL widgets ---
## and strong (initial) foreground color for LABEL & BUTTON widgets ---
## which can be reset to blend with image/theme color.
##+#######################################################################

set hexSelectColor_radbutt "#cfcfcf"
set hexSelectColor_chkbutt "#cfcfcf"

## These background colors may be reset in the 'change_theme' proc.
## These are initial values to prevent an error during the widget definitions,
## and to serve as a default in case they are not reset.
set FG4imgIDlabelFAINT "#6f6f6f"
set FG4imgIDlabel  "#000000"
set FG4imgIDbutton "#000000"
set BG4imgIDbutton "#cfcfcf"

##+#########################################################################
## CREATE IMAGE 'STRUCTURES' for widget backgrounds ---
## 3 types --- button, label, and background.
##
## The actual GIF/PNG files used for these image-ID's are set in the
## GUI INITIALIZATION section at the bottom of this script,
## via a call to the 'change_theme' proc.
##+########################################################################

## Create an image structure for ALL button widgets.

image create photo imgIDbutton


## In order to get the proper width image on 'label' widgets,
## we cannot simply use the '-width' option to 'clip' a long
## image, like we can with the 'button' widget.  We need to
## do an image 'copy' to create an appropriate sized image
## for each label widget.

# image create photo imgIDlabel

## Similarly, we need to do an image 'copy' to create an
## appropriate sized image for the radiobutton and
## checkbutton widgets. So we will do 'image create photo'
## at the definition of each widget.


## Create an image structure for the canvas and text widgets.

image create photo imgIDbkgnd 


##+#######################################################################
## SET FONT VARS for use in the 'font create' statements below.
##+#######################################################################

set guiFONTsize 14
set guiFONT_SMALLsize 12

## For variable width:

set FONT_varwidth \
   " -family {comic sans ms} -size -$guiFONTsize -weight bold -slant roman "

set FONT_SMALL_varwidth \
   " -family {comic sans ms} -size -$guiFONT_SMALLsize -weight normal -slant roman "


## For fixed width:

set FONT_fixedwidth \
   " -family {dejavu sans mono} -size -$guiFONTsize -weight bold -slant roman "

set FONT_SMALL_fixedwidth \
   " -family {dejavu sans mono} -size -$guiFONT_SMALLsize -weight normal -slant roman "


##+#####################################################################
## DEFINE (temporary) FONT NAMES using 'font create'.
## The font names are to be used in '-font' widget specs below.
##+#####################################################################

eval font create fontTEMP_varwidth   $FONT_varwidth
eval font create fontTEMP_fixedwidth $FONT_fixedwidth


eval font create fontTEMP_button  $FONT_varwidth
eval font create fontTEMP_label   $FONT_varwidth

eval font create fontTEMP_text    $FONT_fixedwidth

## Add these widgets to the demo someday?
# eval font create fontTEMP_entry   $FONT_fixedwidth
# eval font create fontTEMP_listbox $FONT_fixedwidth
# eval font create fontTEMP_msg     $FONT_fixedwidth


eval font create fontTEMP_SMALL_button  $FONT_SMALL_varwidth
eval font create fontTEMP_SMALL_label   $FONT_SMALL_varwidth

eval font create fontTEMP_SMALL_text    $FONT_SMALL_fixedwidth

## Someday?
# eval font create fontTEMP_SMALL_entry   $FONT_SMALL_fixedwidth
# eval font create fontTEMP_SMALL_listbox $FONT_SMALL_fixedwidth
# eval font create fontTEMP_SMALL_msg     $FONT_SMALL_fixedwidth


##+#######################################################################
## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS.
## (e.g. padx,pady for Buttons)
##+#######################################################################

## For BUTTON widgets:
   
set PADY_button 0
set PADX_button 0
# set BDwidth_button 2
set BDwidth_button 0


## For LABEL widgets:

set PADY_label 0
set PADX_label 0
# set BDwidth_label 2
set BDwidth_label 0


## For RADIOBUTTON widgets:

set BDwidth_radbutt 0


## For CHECKBUTTON widgets:

set BDwidth_chkbutt 0


## For TEXT widgets:

set BDwidth_text 2


##+#######################################################################
##  SET the top window MIN-SIZE (roughly).
##
## For width: allow for several buttons in the '.fRbuttons' frame:
##               about 2 buttons (Exit,Help), but not
##               an ending info-label. We will allow the user to
##               make this window fairly narrow, but keep the
##               Exit and Help buttons showing.
##
## For height: allow 1 char high for each of the 6 frames:
##       - 'fRbuttons_label' for buttons: Exit,Help - and an info-label
##       - 'fRlabel_scale'   for a scale for font-size, with label
##       - 'fRradiobuttons'  for several radiobuttons for color-theme
##       - 'fRcheckbuttons'  for a checkbutton, to turn images off/on
##       - 'fRcanvas'        for a canvas widget
##       - 'fRtext'          for a text widget
##+#######################################################################

set minWinWidthPx [font measure fontTEMP_varwidth \
   "Exit  Help"]

## Add some pixels to account for right-left-side window decoration
## (about 8 pixels), about 2 widgets x 3 pixels/widget for borders/padding
## for 2 widgets --- 2 buttons.

set minWinWidthPx [expr {14 + $minWinWidthPx}]


## MIN HEIGHT --- allow for about 6 chars high in the 6 stacked frames:

set charHeightPx [font metrics fontTEMP_fixedwidth -linespace]
set minWinHeightPx [expr { 6 * $charHeightPx}]

## Add about 28 pixels for top-bottom window decoration, and
## about 6 frames x 4 pixels/frame for the widgets' borders/padding.

set minWinHeightPx [expr {$minWinHeightPx + 52}]

## FOR TESTING:
#   puts "minWinWidthPx = $minWinWidthPx"
#   puts "minWinHeightPx = $minWinHeightPx"

wm minsize . $minWinWidthPx $minWinHeightPx

## We allow the window to be resizable and we pack the canvas with
## '-fill both' so that the canvas can be enlarged by enlarging the
## window.


## If you want to make the window un-resizable, 
## you can use the following statement.

#  wm resizable . 0 0

#######################################################################
## Set an array to hold text for buttons & labels on the GUI.
##     NOTE: This can aid internationalization. This array can
##           be set according to a nation/region parameter.
#######################################################################

## if { "$VARlocale" == "en"}

set aRtext(buttonEXIT)    "Exit"
set aRtext(buttonHELP)    "Help"
set aRtext(labelINFO)     "Use checkbutton below to turn images off/on."
set aRtext(labelFONTSIZE) "FontSize (pixels):"
set aRtext(labelTHEME)    "Color Theme:"
set aRtext(radbuttBLUE)   "Blue"
set aRtext(radbuttORANGE) "Orange"
set aRtext(radbuttGREEN)  "Green"
set aRtext(radbuttGRAY)   "Gray"

set aRtext(labelIMAGES0or1) "Images on GUI:"
set aRtext(chkbuttIMAGES0or1) ""

## Use the following statement instead of the 2 statements above,
## if we put text in the checkbutton, instead of using a label widget.

# set aRtext(chkbuttIMAGES0or1) "Images on GUI"

## END OF  if { "$VARlocale" == "en"}


##+####################################################################
##+####################################################################
## DEFINE *ALL* THE FRAMES:
##
##   Top-level :
##
##       - 'fRbuttons_label' for buttons: Exit,Help and an info-label
##       - 'fRlabel_scale'   for a scale for font-size
##       - 'fRradiobuttons'  for several radiobuttons for color-themes
##       - 'fRcheckbuttons'  for a checkbutton to turn images off/on
##       - 'fRcanvas'        for a canvas widget
##       - 'fRtext'          for a text widget
##
##+####################################################################
##+####################################################################

## FOR TESTING of expansion of frames (esp. during window expansion):
# set RELIEF_frame raised
# set BDwidth_frame 2

  set RELIEF_frame flat
  set BDwidth_frame 0


frame .fRbuttons_label -relief $RELIEF_frame  -borderwidth $BDwidth_frame

frame .fRlabel_scale   -relief $RELIEF_frame  -borderwidth $BDwidth_frame

frame .fRradiobuttons  -relief $RELIEF_frame  -borderwidth $BDwidth_frame
frame .fRcheckbuttons  -relief $RELIEF_frame  -borderwidth $BDwidth_frame

frame .fRcanvas  -relief $RELIEF_frame  -borderwidth $BDwidth_frame
frame .fRtext    -relief $RELIEF_frame  -borderwidth $BDwidth_frame


##+########################################################
## PACK *ALL* the FRAMES.
##+########################################################

pack .fRbuttons_label \
   -side top \
   -anchor nw \
   -fill none \
   -expand 0

pack .fRlabel_scale \
   -side top \
   -anchor nw \
   -fill y \
   -expand 0

pack .fRradiobuttons \
   -side top \
   -anchor nw \
   -fill none \
   -expand 0

pack .fRcheckbuttons \
   -side top \
   -anchor nw \
   -fill none \
   -expand 0

pack .fRcanvas \
   -side top \
   -anchor nw \
   -fill both \
   -expand 1

pack .fRtext \
   -side top \
   -anchor nw \
   -fill both \
   -expand 1


##+################################################################
##+################################################################
## START DEFINING & PACKING WIDGETS WITHIN THEIR FRAMES. 
##+################################################################
##+################################################################

##+##########################################################
## IN THE '.fRbuttons_label' FRAME --
## DEFINE several BUTTONS
## --- Exit, Help --- and 1 LABEL widget.
##+##########################################################

set widthPXbuttEXIT [font measure fontTEMP_button " $aRtext(buttonEXIT) "]

button .fRbuttons_label.buttEXIT \
   -text "$aRtext(buttonEXIT)" \
   -font fontTEMP_button \
   -padx $PADX_button \
   -pady $PADY_button \
   -relief raised \
   -bd $BDwidth_button \
   -image imgIDbutton \
   -fg $FG4imgIDbutton \
   -compound center \
   -width $widthPXbuttEXIT \
   -command {exit}


set widthPXbuttHELP [font measure fontTEMP_button " $aRtext(buttonHELP) "]

button .fRbuttons_label.buttHELP \
   -text "$aRtext(buttonHELP)" \
   -font fontTEMP_button \
   -padx $PADX_button \
   -pady $PADY_button \
   -relief raised \
   -bd $BDwidth_button \
   -image imgIDbutton \
   -fg $FG4imgIDbutton \
   -compound center \
   -width $widthPXbuttHELP \
   -command {popup_msg_var_scroll "$HELPtext"}


image create photo imgIDlabelINFO

## We will build the image in proc 'change_theme', which is called
## in the GUI INITIALIZATION section at the bottom of this script.

label .fRbuttons_label.labelINFO \
   -text "$aRtext(labelINFO)" \
   -font fontTEMP_label \
   -padx $PADX_label \
   -pady $PADY_label \
   -justify left \
   -anchor w \
   -relief raised \
   -bd $BDwidth_label \
   -width 0 \
   -image imgIDlabelINFO \
   -fg $FG4imgIDlabelFAINT \
   -compound center

#   -fg $FG4imgIDlabel \


##+####################################################
## Pack ALL the widgets in the 'fRbuttons_label' frame.
##+####################################################

pack .fRbuttons_label.buttEXIT \
     .fRbuttons_label.buttHELP \
   -side left \
   -anchor w \
   -fill none \
   -expand 0

pack .fRbuttons_label.labelINFO \
   -side left \
   -anchor w \
   -fill none \
   -expand 0


##+########################################################
## IN THE '.fRlabel_scale' FRAME --
## DEFINE 1 SCALE widget (for specifying font-size),
## with 1 LABEL widget on the left of the scale.
##+########################################################

image create photo imgIDlabelFONTSIZE

## We will build the image in proc 'change_theme', which is called
## in the GUI INITIALIZATION section at the bottom of this script.

label .fRlabel_scale.labelFONTSIZE \
   -text "$aRtext(labelFONTSIZE)" \
   -font fontTEMP_label \
   -padx $PADX_label \
   -pady $PADY_label \
   -justify left \
   -anchor nw \
   -relief raised \
   -bd $BDwidth_label \
   -width 0 \
   -image imgIDlabelFONTSIZE \
   -fg $FG4imgIDlabel \
   -compound center


## We will set 'fontSIZE' (the scale variable) in the
## GUI-init section at the bottom of this script.
##
# set fontSIZE 14

scale .fRlabel_scale.scaleFONTSIZE \
   -orient horizontal \
   -resolution 1 \
   -from 8 -to 16 \
   -digits 0 \
   -length 350 \
   -repeatdelay 1000 \
   -font fontTEMP_label \
   -variable fontSIZE \
   -fg "#ffffff" \
   -troughcolor "#f0f0f0" \
   -command "reset_fontsize"

## The background color ('-bg') for the scale will be
## set in the call to 'change_theme'.


## Pack ALL the widgets in frame 'fRlabel_scale'.

pack .fRlabel_scale.labelFONTSIZE \
   -side left \
   -anchor w \
   -fill y \
   -expand 0

pack .fRlabel_scale.scaleFONTSIZE \
   -side left \
   -anchor w \
   -fill x \
   -expand 0

## WARNING: DO NOT USE '-expand 1'. It makes the scale action 'jumpy'.


##+########################################################
## IN THE 'fRradiobuttons' FRAME --
## DEFINE 1 LABEL widget
## and several RADIOBUTTONS (for 'color-theme').
##+########################################################

image create photo imgIDlabelTHEME

## We will build the image in proc 'change_theme', which is called
## in the GUI INITIALIZATION section at the bottom of this script.

label .fRradiobuttons.labelTHEME \
   -text "$aRtext(labelTHEME)" \
   -font fontTEMP_label \
   -padx $PADX_label \
   -pady $PADY_label \
   -justify left \
   -anchor w \
   -relief raised \
   -bd $BDwidth_label \
   -width 0 \
   -image imgIDlabelTHEME \
   -fg $FG4imgIDlabel \
   -compound center


## VARtheme is the var for the 'color-theme' radiobuttons.
## It will be set in the GUI-init section at the bottom of
## this script.



## Define the BLUE radiobutton.
## It seems to be impossible to get the radiobutton-circle
## on top of the image background along with the text, because
## we need a way to position the text in a spot other than
## the center of the image. We will put the 'Blue' text
## on a separate label widget instead.
##
## It turns out we can put the radiobutton-circle on the
## long button image and clip with '-width 1'. Tk seems
## to allow width for the radiobutton-circle; any width
## specified is in addition to that pre-allocated width.
## '-width 0' causes the entire long button image to be
## placed in the radiobutton widget --- not wanted.
## The '-anchor w' is needed, otherwise the circle is
## not shown.

radiobutton  .fRradiobuttons.radbuttBLUE \
   -variable VARtheme \
   -value "blue" \
   -selectcolor $hexSelectColor_radbutt \
   -relief raised \
   -bd $BDwidth_radbutt \
   -padx $PADX_button \
   -pady $PADY_button \
   -highlightthickness 0 \
   -image imgIDbutton \
   -bg $BG4imgIDbutton \
   -anchor w \
   -width 1

image create photo imgIDlabelBLUE

label .fRradiobuttons.labelBLUE \
   -text "$aRtext(radbuttBLUE)" \
   -font fontTEMP_label \
   -padx $PADX_label \
   -pady $PADY_label \
   -highlightthickness 0 \
   -justify left \
   -anchor w \
   -relief raised \
   -bd $BDwidth_label \
   -width 0 \
   -image imgIDlabelBLUE \
   -fg $FG4imgIDlabel \
   -compound center


## Now define the ORANGE radiobutton and label.

## See notes above the BLUE radiobutton definition.

radiobutton .fRradiobuttons.radbuttORANGE \
   -variable VARtheme \
   -value "orange" \
   -selectcolor $hexSelectColor_radbutt \
   -relief raised \
   -bd $BDwidth_radbutt \
   -padx $PADX_button \
   -pady $PADY_button \
   -highlightthickness 0 \
   -image imgIDbutton \
   -bg $BG4imgIDbutton \
   -width 1 \
   -anchor w

image create photo imgIDlabelORANGE

label .fRradiobuttons.labelORANGE \
   -text "$aRtext(radbuttORANGE)" \
   -font fontTEMP_label \
   -padx $PADX_label \
   -pady $PADY_label \
   -highlightthickness 0 \
   -justify left \
   -anchor w \
   -relief raised \
   -bd $BDwidth_label \
   -width 0 \
   -image imgIDlabelORANGE \
   -fg $FG4imgIDlabel \
   -compound center


## Now define the GREEN radiobutton and label.

## See notes above the BLUE radiobutton definition.

radiobutton  .fRradiobuttons.radbuttGREEN \
   -variable VARtheme \
   -value "green" \
   -selectcolor $hexSelectColor_radbutt \
   -relief raised \
   -bd $BDwidth_radbutt \
   -padx $PADX_button \
   -pady $PADY_button \
   -highlightthickness 0 \
   -image imgIDbutton \
   -bg $BG4imgIDbutton \
   -width 1 \
   -anchor w

image create photo imgIDlabelGREEN

label .fRradiobuttons.labelGREEN \
   -text "$aRtext(radbuttGREEN)" \
   -font fontTEMP_label \
   -padx $PADX_label \
   -pady $PADY_label \
   -highlightthickness 0 \
   -justify left \
   -anchor w \
   -relief raised \
   -bd $BDwidth_label \
   -width 0 \
   -image imgIDlabelGREEN \
   -fg $FG4imgIDlabel \
   -compound center


## Now define the GRAY radiobutton and label.

## See notes above the BLUE radiobutton definition.

radiobutton .fRradiobuttons.radbuttGRAY \
   -variable VARtheme \
   -value "gray" \
   -selectcolor $hexSelectColor_radbutt \
   -relief raised \
   -bd $BDwidth_radbutt \
   -padx $PADX_button \
   -pady $PADY_button \
   -highlightthickness 0 \
   -image imgIDbutton \
   -bg $BG4imgIDbutton \
   -width 1 \
   -anchor w

image create photo imgIDlabelGRAY

label .fRradiobuttons.labelGRAY \
   -text "$aRtext(radbuttGRAY)" \
   -font fontTEMP_label \
   -padx $PADX_label \
   -pady $PADY_label \
   -highlightthickness 0 \
   -justify left \
   -anchor w \
   -relief raised \
   -bd $BDwidth_label \
   -width 0 \
   -image imgIDlabelGRAY \
   -fg $FG4imgIDlabel \
   -compound center


## PACK ALL the widgets in frame 'fRradiobuttons'.

set sepPx 6

pack  .fRradiobuttons.labelTHEME \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 \
   -padx "0 $sepPx"

pack  .fRradiobuttons.radbuttBLUE \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 

pack  .fRradiobuttons.labelBLUE \
   -side left \
   -anchor w \
   -fill none \
   -expand 0  \
   -padx "0 $sepPx"

pack  .fRradiobuttons.radbuttORANGE \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 

pack .fRradiobuttons.labelORANGE \
   -side left \
   -anchor w \
   -fill none \
   -expand 0  \
   -padx "0 $sepPx"

pack  .fRradiobuttons.radbuttGREEN \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 

pack .fRradiobuttons.labelGREEN \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 \
   -padx "0 $sepPx"

pack  .fRradiobuttons.radbuttGRAY \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 

pack .fRradiobuttons.labelGRAY \
   -side left \
   -anchor w \
   -fill none \
   -expand 0 


##+########################################################
## IN THE 'fRcheckbuttons' FRAME --
## DEFINE 1 LABEL & 1 CHECKBUTTON widget
## (to turn images on the GUI on or off).
##+########################################################

image create photo imgIDlabelIMAGES0or1

## We will build the image in proc 'change_theme', which is called
## in the GUI INITIALIZATION section at the bottom of this script.

label .fRcheckbuttons.labelIMAGES0or1 \
   -text "$aRtext(labelIMAGES0or1)" \
   -font fontTEMP_label \
   -padx $PADX_label \
   -pady $PADY_label \
   -justify left \
   -anchor w \
   -relief raised \
   -bd $BDwidth_label \
   -highlightthickness 0 \
   -image imgIDlabelIMAGES0or1 \
   -width 0 \
   -fg $FG4imgIDlabel \
   -compound center


## The checkbutton var 'VARimgs0or1' will be set in the
## GUI-init section at the bottom of this script.
## set VARimgs0or1 1

## Define the IMAGES0or1 checkbutton.
## The situation is similar to the problems with radiobuttons
## with text-on-image:
## It seems to be impossible to get the checkbutton-square
## on top of the image background along with the text, because
## we need a way to position the text in a spot other than
## the center of the image. We will put the 'IMAGES0or1' text
## on a separate label widget instead, to the left of this
## check-mark-only-no-text widget.
##
## It turns out we can put the checkbutton-square on the
## long button image and clip with '-width 1'. Tk seems
## to allow width for the checkbutton-square; any width
## specified is in addition to that pre-allocated width.
## '-width 0' causes the entire long button image to be
## placed in the checkbutton widget --- not wanted.
## The '-anchor w' is needed, otherwise the square is
## not shown.

checkbutton .fRcheckbuttons.chkbuttIMAGES0or1 \
   -variable VARimgs0or1 \
   -selectcolor $hexSelectColor_chkbutt \
   -relief raised \
   -bd $BDwidth_chkbutt \
   -highlightthickness 0 \
   -padx $PADX_button \
   -pady $PADY_button \
   -offrelief flat \
   -indicatoron true \
   -overrelief raised \
   -image imgIDbutton \
   -bg $BG4imgIDbutton \
   -anchor w \
   -width 1


## PACK ALL the widgets in frame 'fRcheckbuttons'.

pack .fRcheckbuttons.labelIMAGES0or1 \
     .fRcheckbuttons.chkbuttIMAGES0or1 \
   -side left \
   -anchor w \
   -fill none \
   -expand 0


##+########################################################
## IN THE 'fRcanvas' frame --
## DEFINE 1 CANVAS widget, with x,y scrollbars.
##+########################################################
##  NOTE: We can trim the image by using the '-width' and
## '-height' options (in pixels) when creating the canvas.
###########################################################

## We could set the initial canvas size according to
## percents (say 30% & 20%) of the screen width and height.

canvas .fRcanvas.canvas \
   -width 300 \
   -height 100 \
   -relief raised \
   -borderwidth 2 \
   -yscrollcommand ".fRcanvas.scrbary set" \
   -xscrollcommand ".fRcanvas.scrbarx set" \

scrollbar .fRcanvas.scrbary \
   -orient vertical -command ".fRcanvas.canvas yview"

scrollbar .fRcanvas.scrbarx \
   -orient horizontal -command ".fRcanvas.canvas xview"

## Put an image on the canvas.

.fRcanvas.canvas create image 0 0  \
   -image imgIDbkgnd \
   -anchor nw \
   -tag CANVASTAGimg 

## Put some text on the canvas.

.fRcanvas.canvas create text 0 0  \
   -text "This is a canvas widget." \
   -font fontTEMP_fixedwidth \
   -anchor nw \
   -tag CANVASTAGtext


## Pack ALL the widgets in the 'fRcanvas' frame.

pack .fRcanvas.scrbary \
   -side right \
   -anchor e \
   -fill y \
   -expand 0

pack .fRcanvas.scrbarx \
   -side bottom \
   -anchor sw \
   -fill x \
   -expand 0

pack .fRcanvas.canvas \
   -side left \
   -anchor nw \
   -fill both \
   -expand 1


##+###########################################################
## IN THE '.fRtext' frame --
## DEFINE 1 TEXT areas --- with x,y scrollbars.
##+###########################################################
## NOTE1: The '-width' and '-height' options are in CHARS,
##        NOT pixels and the like.
## NOTE2: We can trim the image by using the '-width' and
## '-height' options (in chars) when creating the text widget.
##############################################################

text .fRtext.txtDEMO \
   -relief raised \
   -borderwidth 2 \
   -height 9 \
   -width  18 \
   -wrap none \
   -font fontTEMP_text \
   -fg "#000000" \
   -yscrollcommand ".fRtext.scrbary set" \
   -xscrollcommand ".fRtext.scrbarx set"

scrollbar .fRtext.scrbary \
   -command ".fRtext.txtDEMO yview"

scrollbar .fRtext.scrbarx \
   -orient horizontal \
   -command ".fRtext.txtDEMO xview"

## Put some text on the text area.

# .fRtext.txtDEMO delete 1.0 end
# .fRtext.txtDEMO insert end "This is a text widget."

.fRtext.txtDEMO insert 1.0 "This is a text widget.
"

## Put an image on the text area.

.fRtext.txtDEMO image create end \
  -image imgIDbkgnd \
  -align top

## Note to myself: Tried to make a tag here.
## Error in startup script: unknown option "-tag"
##  -tag TEXTTAGimg
## Need another way to tag this, for use in deletion.


##+###################################################
## Pack ALL the text widgets in the '.fRtext' frame.
##+###################################################

pack .fRtext.scrbary \
   -side right \
   -anchor center \
   -fill y \
   -expand 0

pack .fRtext.scrbarx \
   -side bottom \
   -anchor center \
   -fill x \
   -expand 0

pack .fRtext.txtDEMO \
   -side top \
   -anchor nw \
   -fill both \
   -expand 1

##+#################################################
## Keep the user from changing the demo text,
## in case they type in the widget.
##+#################################################

.fRtext.txtDEMO configure -state disabled


##+#####################################################################
## END OF SECTIONS TO SETUP THE GUI.
## ALL FRAMES and WIDGETS are DEFINED.
##+#####################################################################

##+#####################################################################
##+#####################################################################
## DEFINE BINDINGS:
##   -  <ButtonRelease-1> events for the radiobuttons & checkbutton.
##+#####################################################################

bind .fRradiobuttons.radbuttBLUE   <ButtonRelease-1>  "change_theme"
bind .fRradiobuttons.radbuttORANGE <ButtonRelease-1>  "change_theme"
bind .fRradiobuttons.radbuttGREEN  <ButtonRelease-1>  "change_theme"
bind .fRradiobuttons.radbuttGRAY   <ButtonRelease-1>  "change_theme"

bind  .fRcheckbuttons.chkbuttIMAGES0or1 <ButtonRelease-1>  "images_on_off"

## Could use this binding, instead of '-command' on the scale widget.
# bind .fRlabel_scale.scaleSIZE  <ButtonRelease-1>  "reset_fontsize 0"


##+#####################################################################
##+#####################################################################
## DEFINE PROCEDURES:
##      - 'images_on_off'  - for the images off/on checkbutton
##      - 'change_theme'   - for the color-themes radiobuttons
##      - 'reset_fontsize' - for the scale widget
##      - 'popup_msg_var_scroll' - for a Help button
##+#####################################################################
##+#####################################################################

##+#####################################################################
## proc 'images_on_off'
##+#####################################################################
## PURPOSE: Changes the '-image'and '-compound' options on the
##          label and button widgets.
##
## Arguments: via global vars
##
## CALLED BY: button1-release binding on the images-on/off checkbutton
##+#####################################################################
## Note: We start with embellishment (images) ON.
## We set that checkbutton variable in the GUI initialization
## section at the bottom of this script.
##     set VARimgs0or1 1
########################################################################

proc images_on_off {} {

   global VARimgs0or1 widthPXbuttEXIT widthPXbuttHELP

   if {"$VARimgs0or1" == "0"} {

      ## If '-width 0' is not supplied, these widgets x-expand.
      .fRbuttons_label.buttEXIT      configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRbuttons_label.buttHELP      configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRbuttons_label.labelINFO     configure -image "" -compound none -width 0 -relief raised -bd 2

      .fRlabel_scale.labelFONTSIZE   configure -image "" -compound none -relief raised -bd 2

      .fRradiobuttons.labelTHEME     configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRradiobuttons.labelBLUE      configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRradiobuttons.labelORANGE    configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRradiobuttons.labelGREEN     configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRradiobuttons.labelGRAY      configure -image "" -compound none -width 0 -relief raised -bd 2

      .fRradiobuttons.radbuttBLUE    configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRradiobuttons.radbuttORANGE  configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRradiobuttons.radbuttGREEN   configure -image "" -compound none -width 0 -relief raised -bd 2
      .fRradiobuttons.radbuttGRAY    configure -image "" -compound none -width 0 -relief raised -bd 2

      .fRcheckbuttons.labelIMAGES0or1    configure -image "" -compound none -width 0 -relief raised -bd 2

      .fRcheckbuttons.chkbuttIMAGES0or1  configure -image "" -compound none -width 0 -relief raised -bd 2

      ## Using 'delete all' is a rather indiscriminate way to remove
      ## the images from the canvas and text area. In case there are
      ## other objects on these widgets, we have to
      ## use a more specific technique.

      .fRcanvas.canvas          delete -tag CANVASTAGimg         
      # .fRtext.txtDEMO           delete -tag TEXTTAGimg

   } else {

      .fRbuttons_label.buttEXIT      configure -image imgIDbutton    -compound center -width $widthPXbuttEXIT
      .fRbuttons_label.buttHELP      configure -image imgIDbutton    -compound center -width $widthPXbuttHELP
      .fRbuttons_label.labelINFO     configure -image imgIDlabelINFO -compound center -relief flat -bd 0

      .fRlabel_scale.labelFONTSIZE   configure -image imgIDlabelFONTSIZE -compound center -relief flat -bd 0

      .fRradiobuttons.labelTHEME     configure -image imgIDlabelTHEME    -compound center -relief flat -bd 0
      .fRradiobuttons.labelBLUE      configure -image imgIDlabelBLUE     -compound center -relief flat -bd 0
      .fRradiobuttons.labelORANGE    configure -image imgIDlabelORANGE   -compound center -relief flat -bd 0
      .fRradiobuttons.labelGREEN     configure -image imgIDlabelGREEN    -compound center -relief flat -bd 0
      .fRradiobuttons.labelGRAY      configure -image imgIDlabelGRAY     -compound center -relief flat -bd 0

      .fRradiobuttons.radbuttBLUE    configure -image imgIDbutton -width 1 -relief flat -bd 0
      .fRradiobuttons.radbuttORANGE  configure -image imgIDbutton -width 1 -relief flat -bd 0
      .fRradiobuttons.radbuttGREEN   configure -image imgIDbutton -width 1 -relief flat -bd 0
      .fRradiobuttons.radbuttGRAY    configure -image imgIDbutton -width 1 -relief flat -bd 0

      .fRcheckbuttons.labelIMAGES0or1    configure -image imgIDlabelIMAGES0or1   -compound center -relief flat -bd 0

      .fRcheckbuttons.chkbuttIMAGES0or1  configure -image imgIDbutton -width 1 -relief flat -bd 0


      ## Put the bkgnd img back on the canvas and text area.

      .fRcanvas.canvas create image 0 0 \
         -image imgIDbkgnd \
         -anchor nw -tag CANVASTAGimg

      .fRcanvas.canvas raise CANVASTAGtext

      # .fRtext.txtDEMO image create 1.0 \
      #   -image imgIDbkgnd -tag TEXTTAGimg
      ## Need someway to get a tag on this image. This '-tag' yields an error.

   }
   ## END OF  if {$VARimgs0or1 == 1}

}
## END OF PROC  'images_on_off'


##+########################################################################
## PROC 'change_theme'
##+########################################################################
## PURPOSE: Change the color and images on the GUI.
##
## Arguments for input:  global vars VARtheme, aRtext
## Arguments for output: global vars heightPXimgIDbutton, heightPXimgIDlabel
##
## CALLED BY: button1-release on color-theme radiobuttons
##+########################################################################

proc change_theme {} {

   global VARtheme aRtext heightPXimgIDbutton heightPXimgIDlabel \
          FG4imgIDlabel FG4imgIDlabelFAINT BG4imgIDbutton

   ## Set an theme (color and images) according to
   ## the value of the radiobuttons var, VARtheme.
   ## There are 'blue' 'orange' 'green' 'gray' sections below.

   if {"$VARtheme" == "blue"} {

      ## Set the variable for the color-theme radiobuttons.

      set VARtheme "blue"

      ## Set the RGB values for the 'format' and 'tk_setPalette'
      ## statements below.

      ## Bright blue.
      # set R255pal 160
      # set G255pal 200
      # set B255pal 255

      ## Darker blue.
      # set R255pal 186
      # set G255pal 222
      # set B255pal 241

      ## Still darker blue.
      set R255pal 145
      set G255pal 180
      set B255pal 200

      ## Set images for button, label, background.
      ## Note: We allow for the image on labels and buttons being different.

      image create photo imgIDbutton \
         -file "./buttonBkgnd_sheeny_lightBlue_424x28.gif"

      image create photo imgIDlabel \
         -file "./buttonBkgnd_sheeny_lightBlue_424x28.gif"

      ## Set foreground color for the buttons.
      set FG4imgIDbutton "#000000"
      ## Set a background fill color for radio/check-buttons.
      set BG4imgIDbutton "#ecf8fc"

      ## Set foreground color for the labels.
      set FG4imgIDlabel "#000000"
      set FG4imgIDlabelFAINT "#6f6f6f"

      ## Some button/label options:
      ##   buttonBkgnd_glass_blue_A_424x32.gif
      ##   buttonBkgnd_glassy_aqua_496x28.gif
      ##   buttonBkgnd_shaded_paleblue_504x26.gif
      ##   buttonBkgnd_sheeny_blue_432x28.gif
      ##   buttonBkgnd_sheeny_lightBlue_424x28.gif


      image create photo imgIDbkgnd \
      -file "./bigBkgnd_blueWaterAndBeach_1280x744.gif"

      ## Some background options:
      ##   bigBkgnd_RainDrops_onWaterSurface_1280x565.gif
      ##   bigBkgnd_blueWaterAndBeach_1280x744.gif
      ##   bigBkgnd_sunlight_thru_blue_1143x300.gif

   }
   ## END OF 'blue' theme.


   if {"$VARtheme" == "orange"} {

      ## Set the variable for the color-theme radiobuttons.

      set VARtheme "orange"

      ## Set the RGB values for the 'format' and 'tk_setPalette'
      ## statements below.

      ## Orange.
      set R255pal 255
      set G255pal 200
      set B255pal 0

      ## Set images for button, label, background.
      ## Note: We allow for the image on labels and buttons being different.

      image create photo imgIDbutton \
         -file "./buttonBkgnd_glossy_orange_512x28.gif"

      image create photo imgIDlabel \
         -file "./buttonBkgnd_glossy_orange_512x28.gif"

      ## Set foreground color for the buttons.
      set FG4imgIDbutton "#000000"
      ## Set a background fill color for radio/check-buttons.
      set BG4imgIDbutton "#fccf30"

      ## Set foreground color for the labels.
      set FG4imgIDlabel "#000000"
      set FG4imgIDlabelFAINT "#6f6f6f"

      ## Some button/label options:
      ##   buttonBkgnd_glossy_orange_512x28.gif
      ##   buttonBkgnd_shaded_orange_744x28.gif

      image create photo imgIDbkgnd \
         -file "./bigBkgnd_antelope_canyon_sandstone_760x757.gif"

      ## Some background options:
      ##   bigBkgnd_antelope_canyon_sandstone_760x757.gif

   }
   ## END OF 'orange' theme.


   if {"$VARtheme" == "green"} {

      ## Set the variable for the color-theme radiobuttons.

      set VARtheme "green"

      ## Set the RGB values for the 'format' and 'tk_setPalette'
      ## statements below.

      ## Green.
      set R255pal 100
      set G255pal 200
      set B255pal 0

      ## Set images for button, label, background.
      ## Note: We allow for the image on labels and buttons being different.

      image create photo imgIDbutton \
         -file "./buttonBkgnd_sheeny_green_416x28.gif"

      image create photo imgIDlabel \
         -file "./buttonBkgnd_sheeny_green_416x28.gif"

      ## Set foreground color for the buttons.
      set FG4imgIDbutton "#000000"
      ## Set a background fill color for radio/check-buttons.
      set BG4imgIDbutton "#30fc30"

      ## Set foreground color for the labels.
      set FG4imgIDlabel "#000000"
      set FG4imgIDlabelFAINT "#6f6f6f"

      ## Some button/label image options:
      ##   buttonBkgnd_sheeny_green_416x28.gif


      image create photo imgIDbkgnd \
         -file "./bigBkgnd_reliefMap_eastTexas_568x664.gif"

      ## Some background image options:
      ##   bigBkgnd_lightRays_green_766x300.gif
      ##   bigBkgnd_reliefMap_eastTexas_568x664.gif
      ##   bigBkgnd_water_drops_green_1280x1024.gif

   }
   ## END OF 'green' theme.


   if {"$VARtheme" == "gray"} {

      ## Set the variable for the color-theme radiobuttons.

      set VARtheme "gray"

      ## Set the RGB values for the 'format' and 'tk_setPalette'
      ## statements below.

      ## Gray.
      set R255pal 210
      set G255pal 210
      set B255pal 210

      ## Set images for button, label, background.
      ## Note: We allow for the image on labels and buttons being different.

      image create photo imgIDbutton \
         -file "./buttonBkgnd_gradient_gray_592x28.gif"

      image create photo imgIDlabel \
         -file "./buttonBkgnd_gradient_gray_592x28.gif"

      ## Set foreground color for the buttons.
      set FG4imgIDbutton "#000000"
      ## Set a background fill color for radio/check-buttons.
      set BG4imgIDbutton "#cfcfcf"

      ## Set foreground color for the labels.
      set FG4imgIDlabel "#000000"
      set FG4imgIDlabelFAINT "#6f6f6f"

      ## Some button/label image options:
      ##   buttonBkgnd_gradient_gray_592x28.gif

      image create photo imgIDbkgnd \
         -file "./bigBkgnd_lightRays_gray_766x300.gif"

      ## Some background image options:
      ##   bigBkgnd_lightRays_gray_766x300.gif

   }
   ## END OF 'gray' theme.

   ## Set the palette color from the RGB palette values chosen.
   set hexCOLORpal [format "#%02X%02X%02X" $R255pal $G255pal $B255pal]
   tk_setPalette $hexCOLORpal

   ## Put height of the chosen button image in a var.

   set heightPXimgIDbutton [image height imgIDbutton]

   ## Put height of the chosen label image in a var.

   set heightPXimgIDlabel [image height imgIDlabel]


   ## FOR the BUTTONS frame:

   ## Create the image for the 'labelINFO' widget, sized properly.

   set tempWidthPx [font measure fontTEMP_label " $aRtext(labelINFO) "]
   imgIDlabelINFO copy imgIDlabel -from 0 0 $tempWidthPx $heightPXimgIDlabel

   ## Set the foreground (text) color for the 'labelINFO' widget.

   .fRbuttons_label.labelINFO configure -fg $FG4imgIDlabelFAINT


   ## FOR the SCALE frame:

   ## Create the image for the 'labelFONTSIZE' widget, sized properly.
   ## We double the height by using twice the font height and using '-zoom 2'.

   set tempWidthPx [font measure fontTEMP_label " $aRtext(labelFONTSIZE) "]
   imgIDlabelFONTSIZE copy imgIDlabel -from 0 0 $tempWidthPx $heightPXimgIDlabel \
      -to 0 0 $tempWidthPx [expr {2 * $heightPXimgIDlabel}] -zoom 2

   ## Reset the background color for the 'scaleFONTSIZE' widget.

   .fRlabel_scale.scaleFONTSIZE  configure -bg $hexCOLORpal


   ## FOR the RADIOBUTTONS frame:

   ## Create the image for the 'labelTHEME' widget, sized properly.

   set tempWidthPx [font measure fontTEMP_varwidth " $aRtext(labelTHEME) "]
   # image create photo imgIDlabelTHEME
   imgIDlabelTHEME copy imgIDlabel -from 0 0 $tempWidthPx $heightPXimgIDlabel


   ## Create the image for the 'radbuttBLUE' LABEL-widget, sized properly.

   set tempWidthPx [font measure fontTEMP_varwidth " $aRtext(radbuttBLUE) "]
   imgIDlabelBLUE copy imgIDbutton -from 0 0 $tempWidthPx $heightPXimgIDbutton

   ## Set the background color for the 'radbuttBLUE' radiobutton widget.

   .fRradiobuttons.radbuttBLUE configure -bg $BG4imgIDbutton


   ## Create the image for the 'radbuttORANGE' LABEL-widget, sized properly.

   set tempWidthPx [font measure fontTEMP_varwidth " $aRtext(radbuttORANGE) "]
   imgIDlabelORANGE copy imgIDbutton -from 0 0 $tempWidthPx $heightPXimgIDbutton

   ## Set the background color for the 'radbuttORANGE' radiobutton widget.

   .fRradiobuttons.radbuttORANGE configure -bg $BG4imgIDbutton


   ## Create the image for the 'radbuttGREEN' LABEL-widget, sized properly.

   set tempWidthPx [font measure fontTEMP_varwidth " $aRtext(radbuttGREEN) "]
   imgIDlabelGREEN copy imgIDbutton -from 0 0 $tempWidthPx $heightPXimgIDbutton

   ## Set the background color for the 'radbuttGREEN' radiobutton widget.

   .fRradiobuttons.radbuttGREEN configure -bg $BG4imgIDbutton


   ## Create the image for the 'radbuttGRAY' LABEL-widget, sized properly.

   set tempWidthPx [font measure fontTEMP_varwidth " $aRtext(radbuttGRAY) "]
   imgIDlabelGRAY copy imgIDbutton -from 0 0 $tempWidthPx $heightPXimgIDbutton

   ## Set the background color for the 'radbuttGRAY' radiobutton widget.

   .fRradiobuttons.radbuttGRAY configure -bg $BG4imgIDbutton


   ## FOR the CHECKBUTTON frame:

   ## Create the image for the 'labelIMAGES0or1' widget, sized properly.

   set tempWidthPx [font measure fontTEMP_varwidth " $aRtext(labelIMAGES0or1) "]
   imgIDlabelIMAGES0or1 copy imgIDlabel -from 0 0 $tempWidthPx $heightPXimgIDlabel

   ## Set the background color for the 'IMAGES0or1' checkbutton widget.

   .fRcheckbuttons.chkbuttIMAGES0or1 configure -bg $BG4imgIDbutton

}
## END OF PROC  'change_theme'


##+########################################################################
## PROC 'reset_fontsize'
##+########################################################################
## PURPOSE: Change the size of fonts on the GUI.
## CALLED BY: '-command' option of the scale widget
##+########################################################################

proc reset_fontsize { fontsizePx } {

   global VARfontsize

   font configure fontTEMP_varwidth   -size [expr {-$fontsizePx}]
   font configure fontTEMP_fixedwidth -size [expr {-$fontsizePx}]

   font configure fontTEMP_button     -size [expr {-$fontsizePx}]
   font configure fontTEMP_label      -size [expr {-$fontsizePx}]
   font configure fontTEMP_text       -size [expr {-$fontsizePx}]

}
## END OF PROC  'reset_fontsize'


##+########################################################################
## PROC 'popup_msg_var_scroll'
##+########################################################################
## PURPOSE: Report help or error conditions to the user.
## CALLED BY: 'help' button
##+########################################################################
## To have more control over the formatting of the message (esp.
## words per line), we use this 'toplevel-text' method, 
## rather than the 'tk_dialog' method -- like on page 574 of the book 
## by Hattie Schroeder & Mike Doyel,'Interactive Web Applications
## with Tcl/Tk', Appendix A "ED, the Tcl Code Editor".
##+########################################################################

proc popup_msg_var_scroll { VARtext } {

   ## global fontTEMP_varwidth #; Not needed. 'wish' makes this global.
   ## global env

   # bell
   # bell
  
   #################################################
   ## Set VARwidth & VARheight from $VARtext.
   #################################################
   ## To get VARheight,
   ##    split at '\n' (newlines) and count 'lines'.
   #################################################
 
   set VARlist [ split $VARtext "\n" ]

   ## For testing:
   #  puts "VARlist: $VARlist"

   set VARheight [ llength $VARlist ]

   ## For testing:
   #  puts "VARheight: $VARheight"


   #################################################
   ## To get VARwidth,
   ##    loop through the 'lines' getting length
   ##     of each; save max.
   #################################################

   set VARwidth 0

   #############################################
   ## LOOK AT EACH LINE IN THE LIST.
   #############################################
   foreach line $VARlist {

      #############################################
      ## Get the length of the line.
      #############################################
      set LINEwidth [ string length $line ]

      if { $LINEwidth > $VARwidth } {
         set VARwidth $LINEwidth 
      }

   }
   ## END OF foreach line $VARlist

   ## For testing:
   #   puts "VARwidth: $VARwidth"


   ###############################################################
   ## NOTE: VARwidth works for a fixed-width font used for the
   ##       text widget ... BUT the programmer may need to be
   ##       careful that the contents of VARtext are all
   ##       countable characters by the 'string length' command.
   ###############################################################


   #####################################
   ## SETUP 'TOP LEVEL' HELP WINDOW.
   #####################################

   catch {destroy .topmsg}
   toplevel  .topmsg

   # wm geometry .topmsg 600x400+100+50

   wm geometry .topmsg +100+50

   wm title     .topmsg "Note"
   # wm title   .topmsg "Note to $env(USER)"

   wm iconname  .topmsg "Note"


   #####################################
   ## DEFINE & PACK TEXT WIDGET.
   #####################################

   text .topmsg.text \
      -wrap none \
      -font fontTEMP_varwidth \
      -width  $VARwidth \
      -height $VARheight \
      -bg "#f0f0f0" \
      -relief raised \
      -bd 2 \
      -yscrollcommand ".topmsg.scrolly set" \
      -xscrollcommand ".topmsg.scrollx set"

   scrollbar .topmsg.scrolly \
                 -orient vertical \
      -command ".topmsg.text yview"

   scrollbar .topmsg.scrollx \
                -orient horizontal \
                -command ".topmsg.text xview"

   ## Pack the scrollbars BEFORE the text widget,
   ## so that the text does not monopolize the space.

   pack .topmsg.scrolly \
      -side right \
      -anchor center \
      -fill y \
      -expand 0

   ## DO NOT USE '-expand 1' HERE on the Y-scrollbar.
   ## THAT ALLOWS Y-SCROLLBAR TO EXPAND AND PUTS
   ## BLANK SPACE BETWEEN Y-SCROLLBAR & THE TEXT AREA.
                
   pack .topmsg.scrollx \
      -side bottom \
      -anchor center \
      -fill x  \
      -expand 0

   ## DO NOT USE '-expand 1' HERE on the X-scrollbar.
   ## THAT KEEPS THE TEXT AREA FROM EXPANDING.

   pack .topmsg.text \
      -side top \
      -anchor center \
      -fill both \
      -expand 1

   #####################################
   ## DEFINE & PACK OK BUTTON WIDGET.
   #####################################

   button .topmsg.butt \
      -text "OK" \
      -command  "destroy .topmsg"

   pack  .topmsg.butt \
      -side bottom \
      -anchor center \
      -fill none \
      -expand 0

   #####################################
   ## LOAD MSG INTO TEXT WIDGET.
   #####################################

   ##  .topmsg.text delete 1.0 end
 
   .topmsg.text insert end $VARtext
   
   .topmsg.text configure -state disabled
  
}
## END OF PROC 'popup_msg_var_scroll'


set HELPtext "\
\ \ \ \ \ ** HELP for this Tk 'Theme-ing' demo **

  This TkGUI script provides a demo GUI that uses about 7 of the
  commonly used Tk widgets. This is a GUI to demonstrate the ability
  to provide 'themes' for a GUI, even on Linux, using a combination
  of images and colors.

  This demo GUI is 'self-theming' in the sense that radiobuttons
  and checkbuttons on the GUI can be used to reconfigure
  the GUI with different themes (combinations of 'photo'
  images and colors).

  For about 4 types of widgets (label, button, radiobutton,
  checkbutton), the images are backgrounds for text
  on the widget. The text is shown on top of an image
  via the '-compound center' option.

  The widgets shown are label, button, checkbutton, radiobuttons,
  scale, canvas, and text --- 7 widgets out of a family of
  about 18 Tk widgets:

         button, canvas, checkbutton, entry, frame,
         label, labelframe, listbox, menu, menubutton,
         message, panedwindow, radiobutton, scale,
         scrollbar, spinbox, text, toplevel.

 I have chosen widgets that I use the most. I also use
 'frame', 'entry', and 'listbox' widgets frequently, but they
 do not have an '-image' option. So I do not include an
 'entry' or 'listbox' widget on this demo GUI. For the sake of
 blending those kinds of widgets into a 'theme', I may add
 those two widgets in a future version of this demo.

 Although I have never used an '-image' option with the 'text'
 widget and cannot forsee doing so in the future, I include an
 image-on-a-text-widget here --- to demo putting an image on
 a text widget, in case others find that something they may
 want to do.

 The images used in this demo are either
    - a long, rectangular button or label shape
 OR
    - a large, 'fat' background shape.
 The images are 'clipped' to fit the various sized widgets.
 The images are supplied via a GIF or PNG file.

 The image is 'clipped' on each 'button' widget (or 'copied'
 to make a new image of the right size, for 'label', 'radiobutton',
 and 'checkbutton' widgets), usually according to the width
 of the text on the widget.

     (The '-width' option of the 'button' widget seems to
      support clipping the image supplied in the '-image'
      option. But that does not seem to be the case for
      'label', 'radiobutton',  and 'checkbutton' widgets.
      I had to use an image-copy technique to clip the 
      images for those widgets.)

 The image is applied to most widgets with an '-image' option
 and in most cases with the '-compound center' option.
 Exceptions are the scale, canvas, and text widgets.

 The '-compound' option locates the image relative to the text
 on the widget. Options are
           left,right,top,bottom,center,none.

 In this demo script, we only use 'center' and 'none'.

    Unfortunately, there seems to be no way to locate the text
    on the image in a similar fashion, i.e. via compass points.
    So one has to make do with having text centered on the
    image. There is no option to adjust the text to the left side
    of the underlying image, for example. For that kind of
    flexibility, the only option currently available
    (as of Tk/wish 8.6) appears to be to use the canvas widget.
"


##+######################################################
## Additional GUI INITIALIZATION:
## (for most of the APPLICATION-SPECIFIC initialization;
##  i.e. for widget VARIABLES --- NOT widget APPEARANCE
##  PARAMETERS like button padding or '-relief' settings.)
##+######################################################

## Set the variable for the scale widget.

set fontSIZE 14


## Set the variable for the checkbutton widget.
##
## We start with images ON. (See the '-image' option
## in the widget definition statements above.)

set VARimgs0or1 1


## Set an initial theme (color and images) by setting
## the variable of the radiobuttons, $VARtheme, and
## calling the 'change_theme' proc.

set VARtheme "blue"
change_theme


Cropping Button Images (and a surprising difference --- button vs. its cousins --- label, radiobutton, checkbutton)

I provided this discussion on the version 1 demo-Tk-theme-ing page Experiments with flexible THEMES for Tk GUI's, using images and colors, but it is worth repeating here, for your/my convenience.

To provide the image background for the label widgets and 3 types of button widgets, I use a long button (more than 400 pixels wide and about 24 to 28 pixels high) --- and crop this 'base' image to a length suitable to hold the text on the widgets.

We use the '-image' and '-compound' options to put text-on-image on these 4 types of widgets. Unfortunately, only the '-compound center' option is available to put an image under the text. This option does not allow us to position the text on the image in any other location than the center. This proves to create some problems, which are briefly described in the introduction above.


I found a rather surprising difference in the 'cropping' capability of the 'button' widget in comparison to its cousins --- the 'label', 'radiobutton', and 'checkbutton' widgets.

I could provide the long 400-plus-pixel image filename in the '-image' option of 'button' and simply crop the image by using the '-width' parameter of button.

However, for the label-radiobutton-checkbutton widgets, the '-width' parameter would not perform the 'crop'. I had to use 'image create' to create new 'image structures', for each widget, to which I could apply a '-width' parameter --- to get an image to use in the '-image' option of the label-radiobutton-checkbutton widgets.

I suppose that the Tk developers did not notice this difference because they have probably used the '-compound center' (text-ON-image) option in a very small number of 'use-cases'.

Anyway, I am pleased to report that I was able to find a work-around.


Enhancements to improve the look

There is still one thing that stands out to me as an area where the GUI 'look' could be improved:

  • there seems to be no way to put an image-background behind the 'scale' widget (a TIP item for Tk 9.0?)

In regard to the lack of an image behind the 'scale' widget:

There is a possible work-around. One could make a scale-like widget from a frame widget containing a label widget and 2 button widgets (like Suchenwirth's 'spinner' widget that he published on the spinbox page, or like my 'miniscale' widget that I published on the A color-gradient-button-maker GUI with 6 'miniscale' widgets page). Then one could use the -image' option of the 'label' and 'button' widgets.

It's not ideal --- but at least, for those who find the 'scale-without-an-image-background' ugly, there is an opportunity to reduce the ugliness.

I may try that technique, in a version 3 of this script, to see if I can improve the look of the GUI in the area of the scale widget.


RLE (2012-11-08): The pure Tk method of putting a custom image behind the scale (I presume you mean as the image of the "tray" of the scale) is to build the scale itself from a canvas widget. The canvas widget will allow an image as the "tray" below the active control knob of the scale. The two hard parts are then working out all the drawing elements to make a proper "scale" widget, and working out all the Tk bindings to make it work as a scale. Once that is done, it works the same as a regular scale, only with an image inside the tray.

uniquename 2012nov09 To RLE: Thanks for the suggestion. Funny thing: As I was lying in bed this morning, before getting up, I was thinking about how building the scale-substitute out of a label and 2 buttons might not allow for changing the scale as quickly as with the Tk 'scale' widget. I thought: How can I make a widget more like the 'scale' widget --- with a slider-bar?

It immediately occurred to me to try the 'canvas' widget --- which I used successfully to build 'toolchests' with nice images, getting around the text-centered-on-image (no text-on-left-of-image option) problem in using 'button' widgets. Like you say, the difficulty now is in working out the drawing elements and the bindings. But, like you indicate, the nice thing is that I should be able to have an area-covering image behind the movable-slider-bar and fixed-tray (and the moving-changing numeric text label). The tray could have a constant-color background, like the 'indicators' of the radio and check buttons.

Sheesh! That's one more project to add to my list of about 10-plus pending projects on my Tk-Tcl to-do list. I can't code fast enough! And the more I code, the more projects I think of to do. I am getting faster, but not fast enough. As I have mentioned elsewhere: Ousterhout, you really started something. I've become a Tk-with-Tcl addict.


In summary, I think I have found a set of 'techniques', 'tricks', and 'work-arounds' that may allow me to construct some pretty good-looking 'themed' Tk GUI's --- on Linux even, everybody's step-child, it seems.