A non-obfuscated color selector GUI

uniquename - 2012aug06

Way back around 1998 when I was first learning the Tcl-Tk language, I would do web searches on keyword strings such as 'usr bin wish button' or 'usr bin wish scale rgb' to find examples of complete Tcl-Tk scripts --- because the code 'snippets' in Tcl-Tk books and tutorials were not very helpful in creating 'production' scripts (relatively quickly).

In doing those kinds of web searches, I ran across a Tcl-Tk script that offered a nice, simple color selector GUI consisting of 3 'scale' widgets for setting RGB values (from 0 to 255) --- along with a 'frame' widget color-swatch for dynamically showing the color as the user moved any of the three scale-sliders with the mouse-button-1.

I used the word 'non-obfuscated' in the title of this page because many of the color selectors that I have seen are quite confusing. They hit my eyes with so many features --- color shaded disks, RGB sliders, HS-whatever sliders, etc. etc. --- that I get a headache (and waste too much time) trying to figure out how to use them.

This color selector is so simple that it is obvious 'from the git-go' how to use it. And yet it has done all that I need it to do in all the 'use cases' that I have encountered so far.

The original script was posted in a web page for a computer science class (probably by a professor or student) at an Australian university (USQ = the University of Southern Queensland). When I tried going back to the web page around 2004, I found it was gone. So I am glad that I 'harvested' that script code before it disappeared into that great bit bucket in the sky.

(The URL for that dearly-departed Australian web page is in the comments of the code below.)


Changes to the Australian script :

I changed the original script quite a bit. Some of the changes that I can remember are:

1) The 'place' geometry manager was originally used in the script. I switched to the pack command.

2) The original script showed the current RGB value in '#rrggbb' hex format, in a label widget. Like the color swatch, the hex values changed dynamically as the sliders were moved with the mouse.

I changed the label widget to a text widget, so that one could copy-and-paste the hex-string with a 'left mouse button swipe' for the 'copy' and a middle-mouse-button click for the 'drop' ('paste') --- handy for pasting into a text editor window containing some Tk code or some HTML code.

I also added a text widget to show the RGB values (between 0 and 255) as percents (between 0 and 100).

3) Using a pack forget command technique, I made a Toggle-Side button on the GUI so that I could quickly switch the color swatch from one side of the GUI to the other.

4) I made a "put_vars" proc that uses 'puts' to output the current RGB values (decimal and hex), when a 'UseIt' button is clicked --- so that I can use the color selector GUI within shell scripts and within other Tcl-Tk scripts --- to pass a selected RGB value back to the calling script.

5) There are a lot of changes that I made to the script to share parameter setting code that is used in other Tk scripts of mine.

6) The font setting code was updated to use the newer constructs in Tk that came in 8.x releases of Tk.

7) I added some argc,argv code to, optionally, accept initial RGB values from the command line.

8) I added some 'catch' statements to, optionally, accept initial RGB values from environment variables --- R255, G255, B255.

9) I added some 'catch' statements to, optionally, accept window and window-icon titles from environment variables --- and to, optionally, accept window geometry (location or location-and-size) from an environment variable.

Here is an image of the resultant color selector GUI.

colorSelectorGUI_screenshot_572x194.png

After I retired and started assembling the software in my 'Freedom Environment' software system (see [1 ]), I used the color selector Tk script as a palette-color setting utility in the 'xpg', 'feAppMenus, and 'feHandyTools' subsystems of my Freedom Environment software.

I provide all that FE code as free and open source code. A lot of the FE Tcl-Tk scripts (such as the code for the 'xpg' utility) are really too long for a page on this Tcl-Tk wiki. But the code for the color-selector utility is probably no longer than some of the longer scripts that have been presented here.

So, to help make sure that the code from that Australian professor (along with my enhancements) does not disappear into the Internet Graveyard of Dead Links, here is a resurrection of the code.

I have 'left in' many of my comments that explain the usage of the GUI and the structure and intent of the code.

In my FE subsystems, I use some Tk 'include' files in my Tk scripts to provide some parameter setting that is shared with other utility scripts. I have replaced the corresponding 'source' statements with the essential Tk statements from those 'include' code-files.

(Some of the 'include' statements involving parameters for 'listbox' and 'entry' and 'message' widgets, widgets not used in this GUI, may be left in this code --- but commented, for the most part. Those statments can be useful if other GUIs are made using this code as a starting point.)

As I do with all my Tk scripts, I have put the four main pack parameters --- '-side', '-anchor', '-fill', '-expand' --- on the 'pack' command for the various frames and widgets. That helps me when I am initially testing the behavior of a GUI (the various widgets within it) as I resize the main window.

For this particular GUI, I have used the statement

wm resizeable . 0 0

to make the window (and its widgets) a fixed size --- since I have found no advantage in having the color swatch change size --- and no advantage to having the scale widgets change size.

However, if anyone sees an advantage to allowing the GUI to change size, they can comment the 'wm resizeable' statement --- and then experiment with the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various widgets --- to get the widget behavior that they want.

(Since I did some experimenting with the GUI before making it non-resizable, the pack parameters in this code are probably at reasonable settings. So if you comment out the 'wm resizeable' statement, the GUI elements may resize --- or not resize --- nicely as you change window size.)


 Code for the Tk script 'select_RGBcolor_standAlone.tk' :
#!/usr/bin/wish -f
##
##+#######################################################################
## NOTE:
##   If the 'wish' interpreter is in another directory, like
##   /usr/local/bin, you, as root, can make a soft-link from 'wish' there
##   to /usr/bin/wish --- with a command like
##             ln -s /usr/local/bin/wish  /usr/bin/wish
##   The form of this command:
##             ln -s <filename-of-existing-file> <name-of-new-link-file>
##+#######################################################################
## Tk SCRIPT NAME:   select_RGBcolor_standAlone.tk
##
##                    'stand-alone' means no 'source' statements,
##                    which were used in the original RGB color-selector utility
##                    of the 'xpg' and 'feAppMenus' Freedom Environment (FE)
##                    systems available at www.freedomenv.com.
##
## In some Tk scripts in which I use this color-selector as an
## 'external' Tk utility, I have assumed that this code is in a file
## named 'sho_colorvals_via_sliders3rgb.tk'.
##
## The 'sliders' refers to the 3 Tk 'scale' widgets for selecting RGB colors.
##
## The original 'sho_colorvals_via_sliders3rgb.tk' script was in the
## directories  $FEDIR/tkGUIs  --- where $FEDIR is the installation
## directory of an FE subsystem. The 'sourced-in' code files were in '.tki'
## Tk include files in  $FEDIR/includes_tk  directories.
## Reference: www.freedomenv.com
##+#######################################################################
## PURPOSE:  This TkGUI script provides a GUI for selecting Red-Green-Blue
##           values,  from 0 thru 255, via slider bars.
##
##           For any slider bar change, this GUI script
##           immediately shows the color as the background color of a
##           frame widget (a 'color swatch') in a corner of the GUI
##           window (covering about 20% of the window).
##
##           Also the GUI shows the current color's hex (and per-cent)
##           RGB values in two small text widgets about 12 characters long.
##
## SOME USES:
##
##       1)  Useful in determining color specification in decimal or hex
##           values to (nearly) MATCH A GIVEN COLOR. The user can drag
##           this GUI to a portion of the screen's 'wallpaper', and use
##           the slider bars to find (near) color matches. Similarly, bring
##           this GUI next to an image viewer window, to find near-color
##           matches in the image.
##
##       2)  Also useful in DETERMINING SUITABLE BACKGROUND COLORS
##           for black/white text.
##
##       3)  IN A SHELL SCRIPT OR ANOTHER TK SCRIPT, this Tk script can
##           ACT AS A COLOR SELECTOR by passing the current color to stdout
##           (in decimal and hex), when the OK/UseIt button is clicked.
##           Example output string:  0 156 255 009CFF
##
##+#######################################################################
## SOURCE (and CREDIT-TO):
##
##  This script was based on an example from Australia (circa 1999) at
##        http://www.sci.usq.edu.au/~devoil/66309/tut2.html
##  (Author's name unknown. The script may have been based on the Tk
##   color selector GUI that was announced by Ousterhout around 1996.
##   It may have been intended as a simplification of that GUI.)
##
##  The 'place' commands in the Australian script were replaced by
##  'pack' commands. Also the per-cents display was added.
##
##  The 'ToggleSide' button was added, to be able to switch the
##  color swatch to the left side of the GUI. That helps, for
##  example, when trying to find a color that matches the left
##  side of the screen (the desktop background).
##
##  The hex-RGB-code used to be shown in a label widget.
##  It is now shown in a text widget so that the user can
##  mouse-copy-and-paste the hex-RGB-code into another window,
##  such as a text-editor window editing an HTML page or a
##  Tk script.
##
##+#####################################################################
## CALLED BY:  'make_chest.tk'  in  $FEDIR/tkGUIs of 'feAppMenus'
##             and 'shofil.tk' (the core of the FE 'xpg' utility)
##             and probably by more FE scripts in the future.
##+#####################################################################
## INPUTS:  The user slides the slider bars.  Initial RGB vals can be set
##          as described in the next section, 'CALL FORMAT'.
##
## OUTPUT:  The color-swatch and hex-and-percent RGB values displayed on
##          the Tk window.
##
##          Also the last RGB slider settings are passed to stdout
##          as a string giving decimal and hex values of the color.
##
##          Sample output string:  0 156 255 009CFF
##
##+#####################################################################
## CALL FORMAT:
##
##  $FEDIR_TKGUIS/sho_colorvals_via_sliders3rgb.tk  [r255 g255 b255]
##
##      where r255 g255 b255 represent integers between 0 and 255,
##      and the values are ignored if there are not exactly three.
##      If no values are entered, the defaults are 0 156 255 or
##      some such triplet.
##
##   OR
##
##      use environment variables R255, G255, B255 to initialize the sliders.
## -----------------------------------------------------------------------
##   EXAMPLE CALLS in a shell script:
##                              (Could also be called in a tcl-tk script.
##                               See the tcl-tk scripts mentioned in the
##                               'CALLED BY' section above.)
##
##    1)    R255=80
##          G255=156
##          B255=255
##          export R255 G255 B2555
##
##          TEMP=`$FEDIR_TKGUIS/sho_colorvals_via_sliders3rgb.tk`
##  OR
##    2)
##          TEMP=`$FEDIR_TKGUIS/sho_colorvals_via_sliders3rgb.tk 80 156 255`
##       or
##          TEMP=`$FEDIR_TKGUIS/sho_colorvals_via_sliders3rgb.tk`
##
##
## (Note: The values in TEMP can be extracted with a command like
##  'cut' or 'awk', in a shell script.)
##+########################################################################
## 'CANONICAL' STRUCTURE OF THIS CODE:
##
##  0) Set general window parms (win-name, win-position, win-color-scheme,
##     fonts, widget-geom-parms, text-array-for-labels-etc, win-size-control).
##
##  1a) Define ALL frames (and sub-frames).
##  1b) Pack   ALL the frames and sub-frames.
##
##  2) Define & pack all widgets in the frames, frame by frame.
##                                When ALL widgets are defined
##                                for a frame, pack them.
##
##  3) Define key and mouse/touchpad/touch-sensitive-screen 'event'
##     BINDINGS, if needed.
##  4) Define PROCS, if needed.
##  5) Additional GUI INITIALIZATION (typically with
##          one or two procs in section 4), if needed.
##
##+#################################
## The code structure in more detail, for this particular script:
##
##  1a) Define ALL frames:
##        Top-level : 'fRsliders', 'fRpreview' , 'fRbottom'
##        Sub-frames: 'fRsliders.red', 'fRsliders.green' , 'fRsliders.blue'
##
##        'fRsliders' and 'fRpreview' are to be on the top of the GUI,
##         on the left and right, respectively.
##        'fRbottom' is to be on the bottom of the GUI.
##
##  1b) Pack ALL frames.
##
##  2) Define & pack all widgets in the frames -- basically going through
##     frames & their interiors in top-to-bottom and/or left-to-right order:
##
##      - 'fRsliders'     to contain 3 sliderbars (Tk 'scale' widgets)
##
##      - 'fRpreview'     to contain only its background color; to display
##                        the color specified by the sliderbar settings
##
##      - 'fRbottom'      to contain several buttons and label & text widgets
##                        to display the current % [0 to 100] and hex [ 00
##                        to FF ] RGB values of the color.
##
##  3) Define BINDINGS:  none currently
##
##  4) Define PROCS:
##       'color_update'           - called by the '-command' option on the
##                                  3 RGB 'scale' widgets.
##       'toggle_side'            - called by the 'ToggleSide' button
##       'put_vars'               - called by the 'UseIt' button
##       'popup_msgVarWithScroll' - called by the 'Help' button
##
##  5) Additional GUI INITIALIZATION:  none, except for setting
##                                     the HELPtext var for the Help button.
##
##+#######################################################################
## DEVELOPED WITH: originally with (Tcl 7.4)-(Tk 4.0) on SGI/Irix (Unix)
##                 circa 1999 and lately (circa 2011) with Tcl-Tk 8.5 on
##                 Ubuntu 9.10 (2009 october, 'Karmic Koala).
##
##   wish> puts "$tcl_version $tk_version"
##   showed
##   7.4 4.0
##   then
##   8.5 8.5
##+########################################################################
## FE system Copyright 2006+ by Blaise Montandon
##+########################################################################
## MAINTENANCE HISTORY:
##             This Tk script is based on a sample Tk script found at
##             http://www.sci.usq.edu.au/~devoil/66309/tut2.html in 1999.
##------------------------------------------------------------------------
## Created by: Blaise Montandon 2008mar31 Started version for the FE
##                                        system, on Linux, Mandriva 2007.
## ...
## ...
## Changed by: Blaise Montandon 2012aug   Converted the 2011oct05 version that
##                                        is/was used the FE subsystems,
##                                        to be 'stand-alone'. I.e. the code
##                                        from Tk 'include' files that are
##                                        incorporated into the script code
##                                        via 'source' statements, was
##                                        hard-coded into this script ---
##                                        to make a 'stand-alone' script
##                                        to donate to https://wiki.tcl-lang.org.
## Changed by: Blaise Montandon 2012nov03 Added an alternate, shorter name
##                                        for this script, in comments above.
## Changed by: Blaise Montandon 2014mar13 Added 'aRtext' array for ease of
##                                        internationalization.
##                                        Added some relief, borderwidth, and
##                                        padding parameters to widget
##                                        definition statements --- to facilitate
##                                        experiments in changing/improving
##                                        the appearance of the GUI.                                       
##+############################################################################

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

wm title . \
   "Colors in Decimal & PerCent & Hex  - version for wiki.tcl.tk"

wm iconname . "ColorSelector"

# catch { wm title    . "$env(FE_WIN_TITLE)" }
# catch { wm iconname . "$env(FE_ICON_TITLE)" }


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

wm geometry . +50+50

# catch {eval wm geometry . "$env(FE_COLORSEL_GEOM)" }


##+#######################################################################
## SET COLOR SCHEME (palette) FOR THE WINDOW
## --- and the background color for some widgets.
##+#######################################################################

##  Gray palette
set r255 210
set g255 210
set b255 210

set HEXCOLOR_pal [format "#%02X%02X%02X" $r255 $g255 $b255]
tk_setPalette $HEXCOLOR_pal


## Set color background for some widgets.

set troughBKGD  "#f0f0f0"

set textBKGD    "#c0c0c0"

# set entryBKGD   "#f0f0f0"
# set radbuttBKGD "#f0f0f0"
# set chkbuttBKGD "#f0f0f0"
# set listboxBKGD "#f0f0f0"


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

set FONTsize 14
set FONT_SMALLsize 12

## For variable width:

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

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


## For fixed width:

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


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


##+#####################################################################
## DEFINE (temporary) 'FONT-NAMES using 'font create'.
## The font names are to be used in '-font' widget specs below.
##
## Generally we use variable-width fonts for BUTTONS and LABELS
## --- and fixed-width fonts for ENTRY and LISTBOX widgets.
##
## If we do not need to keep text columns aligned, we may
## use variable-width font in TEXT and MESSAGE widgets.
##+#####################################################################

eval font create fontTEMP_button    $FONT_varwidth
eval font create fontTEMP_label     $FONT_varwidth
eval font create fontTEMP_scale     $FONT_varwidth
eval font create fontTEMP_varwidth  $FONT_varwidth

  eval font create fontTEMP_text        $FONT_fixedwidth
# eval font create fontTEMP_entry       $FONT_fixedwidth
# eval font create fontTEMP_listbox     $FONT_fixedwidth
  eval font create fontTEMP_fixedwidth  $FONT_fixedwidth

## If we need a smaller font in some of these widgets,
## we use the following.

# 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
# eval font create fontTEMP_SMALL_entry   $FONT_SMALL_fixedwidth
# eval font create fontTEMP_SMALL_listbox $FONT_SMALL_fixedwidth


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

## For BUTTON widgets:

set PADX_button 0
set PADY_button 0
set BDwidthPx_button 2
## We use relief "raised" for all 'button' widgets.
set RELIEF_button "raised"

## For LABEL widgets:

set PADXpx_label 0
set PADYpx_label 0
set BDwidthPx_label 2
## Relief must be flat, groove, raised, ridge, solid, or sunken.
# set RELIEF_label_hi "ridge"
set RELIEF_label_lo "flat"


## SCALE geom parameters:

set BDwidthPx_scale 2
set initScaleLengthPx 350
set scaleThickPx 10


## For ENTRY widgets:

# set BDwidth_entry 2
## We use relief "sunken" for all 'entry' widgets.
# set RELIEF_entry "sunken"


## For LISTBOX widgets:

# set BDwidth_listbox 2


## For TEXT widgets:

set BDwidth_text 2
# set RELIEF_numtext "sunken"
  set RELIEF_numtext "ridge"
# set RELIEF_numtext "groove"


##+####################################################################
## Set a TEXT-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"}

## For 'fRsliders' frame:

set aRtext(labelRED)   "Red"
set aRtext(labelGREEN) "Green"
set aRtext(labelBLUE)  "Blue"


## For 'fRpreview' frame:

## NO TEXT in this frame-only widget.


## For 'fRbottom' frame:

set aRtext(buttonOK)     "UseIt"
set aRtext(buttonEXIT)   "Cancel"
set aRtext(buttonHELP)   "Help"
set aRtext(buttonSIDE)   "ToggleSide"

set aRtext(labelPCENT)  "RGB-%s:"
set aRtext(labelHEX)    "RGB-in-Hex:"

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


##+################################################
## SET THE WINDOW SIZE.
## (We 'fix' the size rather than setting a minsize
##  and allowing the window to expand.)
##+################################################

wm resizable . 0 0


##+########################################################################
##+########################################################################
##
## GET INPUT PARM VALUES --
## i.e. set R255init G255init B255init from
##
##    1)  arguments passed to this script
## OR
##    2)  environment vars R255, G255, B255.
##
##+########################################################################
##+########################################################################
##  Example argc/argv processing:
##
## if {$argc == 0} {
##    set VARtext "$env(CONFIRM_TEXT)"
## } else {
##    set VARtext [lindex $argv 0]
## }
##+########################################################################

if {$argc == 3} {

   set R255init [lindex $argv 0]
   set G255init [lindex $argv 1]
   set B255init [lindex $argv 2]

} else {

   # set R255init 40
   set R255init 0
   catch { set R255init "$env(R255)" }

   # set G255init 80
   set G255init 156
   catch { set G255init "$env(G255)" }

   # set B255init 120
   set B255init 255
   catch { set B255init "$env(B255)" }

}



##+####################################################################
##+####################################################################
## DEFINE *ALL* THE FRAMES:
##   TOP-LEVEL FRAMES:
##     - 'fRsliders'  - to contain 3 sliderbars.
##     - 'fRpreview'  - to contain only its background; to display
##                      the color specified by the sliderbar settings.
##     - 'fRbottom'   - to contain several buttons (UseIt,Cancel,etc),
##                      as well as 2 label & 2 text widgets to
##                      display the current per-cent and
##                      hex RGB-values of the color.
##
##  'fRsliders' & 'fRpreview' are packed on left & right.
##
##   SUB-FRAMES:
##     - 'fRsliders.fRred'     (to contain 1 label, 1 sliderbar)
##     - 'fRsliders.fRgreen'   (to contain 1 label, 1 sliderbar)
##     - 'fRsliders.fRblue'    (to contain 1 label, 1 sliderbar)
##+####################################################################
##+####################################################################

## FOR TESTING: (of size of frames during window resizing)
# set RELIEF_frame raised
# set BDwidth_frame 2

set RELIEF_frame flat
set BDwidth_frame 0


frame .fRsliders   -relief $RELIEF_frame   -bd $BDwidth_frame

frame .fRpreview   -relief raised   -bd 4  -height 140 -width 140

frame .fRbottom    -relief $RELIEF_frame   -bd $BDwidth_frame


frame .fRsliders.fRred    -relief $RELIEF_frame  -bd $BDwidth_frame

frame .fRsliders.fRgreen  -relief $RELIEF_frame  -bd $BDwidth_frame

frame .fRsliders.fRblue   -relief $RELIEF_frame  -bd $BDwidth_frame


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

pack  .fRbottom \
   -side bottom \
   -anchor w \
   -fill x \
   -expand 1

##+##########################################
## NOTE:  Need to pack the 'fRbottom' frame
##        before the 'fRsliders' & 'fRpreview'
##        frames -- otherwise the 'bottom'
##        frame comes out in the lower-right
##        of the window, instead of below
##        'sliders' & 'preview'.
##
## Alternatively, we could define an additional
## frame to contain the 'sliders' & 'preview'
## frames.
##+##########################################

set LR_side "left"

##+##########################################
## NOTE:  The variable 'LR_side' will
##        be used to help toggle the position
##        of 'preview' to left or right.
##+##########################################

pack .fRsliders \
     .fRpreview \
   -side $LR_side \
   -anchor w \
   -fill both \
   -expand 1

pack .fRsliders.fRred \
     .fRsliders.fRgreen \
     .fRsliders.fRblue \
   -side top \
   -anchor w \
   -fill x \
   -expand 1


##+################################################################
## OK. The frames and sub-frames are defined.
##+################################################################
## START DEFINING & PACKING WIDGETS WITHIN THEIR FRAMES.
##+################################################################
##+################################################################

##+########################################################
## IN THE 'fRsliders' frame,
## DEFINE 3 LABELS and 3 SLIDERBAR WIDGETS. THEN PACK THEM.
##+########################################################

## RED

label .fRsliders.fRred.label \
   -text "$aRtext(labelRED)" \
   -width 8 \
   -font fontTEMP_label \
   -justify left \
   -anchor w \
   -padx $PADXpx_label \
   -pady $PADYpx_label \
   -bd $BDwidthPx_label \
   -relief $RELIEF_label_lo

scale .fRsliders.fRred.scale \
   -orient horizontal \
   -from 0 -to 255 \
   -resolution 1 \
   -digits 0 \
   -length $initScaleLengthPx \
   -font fontTEMP_scale \
   -showvalue true \
   -bd $BDwidthPx_scale \
   -relief flat \
   -highlightthickness 0 \
   -width $scaleThickPx \
   -troughcolor $troughBKGD \
   -command {color_update}

.fRsliders.fRred.scale set $R255init

## GREEN

label .fRsliders.fRgreen.label \
   -text "$aRtext(labelGREEN)" \
   -width 8 \
   -font fontTEMP_label \
   -justify left \
   -anchor w \
   -padx $PADXpx_label \
   -pady $PADYpx_label \
   -bd $BDwidthPx_label \
   -relief $RELIEF_label_lo

scale .fRsliders.fRgreen.scale \
   -orient horizontal \
   -from 0 -to 255 \
   -resolution 1 \
   -digits 0 \
   -length $initScaleLengthPx \
   -font fontTEMP_scale \
   -showvalue true \
   -bd $BDwidthPx_scale \
   -relief flat \
   -highlightthickness 0 \
   -width $scaleThickPx \
   -troughcolor $troughBKGD \
   -command color_update

.fRsliders.fRgreen.scale set $G255init

## BLUE

label .fRsliders.fRblue.label \
   -text "$aRtext(labelBLUE)" \
   -width 8 \
   -font fontTEMP_label \
   -justify left \
   -anchor w \
   -padx $PADXpx_label \
   -pady $PADYpx_label \
   -bd $BDwidthPx_label \
   -relief $RELIEF_label_lo

scale .fRsliders.fRblue.scale \
   -orient horizontal \
   -from 0 -to 255 \
   -resolution 1 \
   -digits 0 \
   -length $initScaleLengthPx \
   -font fontTEMP_scale \
   -showvalue true \
   -bd $BDwidthPx_scale \
   -relief flat \
   -highlightthickness 0 \
   -width $scaleThickPx \
   -troughcolor $troughBKGD \
   -command {color_update}

.fRsliders.fRblue.scale set $B255init


##+#################################################
## PACK 3 LABELS & 3 SCALES IN 'fRsliders' FRAME.
##+#################################################

pack .fRsliders.fRred.label \
   -side left \
   -anchor w \
   -fill none \
   -expand 0

pack .fRsliders.fRred.scale \
   -side left \
   -anchor w \
   -fill x \
   -expand 1

pack .fRsliders.fRgreen.label \
   -side left \
   -anchor w \
   -fill none \
   -expand 0

pack .fRsliders.fRgreen.scale \
   -side left \
   -anchor w \
   -fill x \
   -expand 1

pack .fRsliders.fRblue.label \
   -side left \
   -anchor w \
   -fill none \
   -expand 0

pack .fRsliders.fRblue.scale \
   -side left \
   -anchor w \
   -fill x \
   -expand 1


##+###############################################################
## IN THE 'fRbottom' frame,
## DEFINE several BUTTONS -- 'UseIt', 'Cancel', 'ToggleSide','Help'
## AND
## two pairs of LABEL-and-TEXT widgets
## (for RGB colors in percents and hex).
##
## THEN PACK ALL THE WIDGETS.
##
## (We us 'text' widgets, rather than 'label' or 'message'
##  widgets, so that it is possible to paste the percent/hex
##  values to another window.)
##+########################################################

button .fRbottom.butReturn \
   -text "$aRtext(buttonOK)" \
   -font fontTEMP_button \
   -padx $PADX_button \
   -pady $PADY_button \
   -bd $BDwidthPx_button \
   -relief raised \
   -command {put_vars}

# -text "OK"

button .fRbottom.butCancel \
   -text "$aRtext(buttonEXIT)" \
   -font fontTEMP_button \
   -padx $PADX_button \
   -pady $PADY_button \
   -bd $BDwidthPx_button \
   -relief raised \
   -command {exit}

button .fRbottom.butTogside \
   -text "$aRtext(buttonSIDE)" \
   -font fontTEMP_button \
   -padx $PADX_button \
   -pady $PADY_button \
   -bd $BDwidthPx_button \
   -relief raised \
   -command {toggle_side}

button .fRbottom.butHelp \
   -text "$aRtext(buttonHELP)" \
   -font fontTEMP_button \
   -padx $PADX_button \
   -pady $PADY_button \
   -bd $BDwidthPx_button \
   -relief raised \
   -command {popup_msgVarWithScroll .topHelp "$HELPtext"}


label .fRbottom.labhex \
   -text "$aRtext(labelHEX)" \
   -width 11 \
   -font fontTEMP_label \
   -justify left \
   -anchor e \
   -padx $PADXpx_label \
   -pady $PADYpx_label \
   -bd $BDwidthPx_label \
   -relief $RELIEF_label_lo

text .fRbottom.txthex \
   -height 1 \
   -width  8 \
   -wrap none \
   -font fontTEMP_text \
   -bd $BDwidth_text \
   -relief $RELIEF_numtext \
   -bg $textBKGD

label .fRbottom.labpcnt \
   -text "$aRtext(labelPCENT)" \
   -width 8 \
   -font fontTEMP_label \
   -justify left \
   -anchor e \
   -padx $PADXpx_label \
   -pady $PADYpx_label \
   -bd $BDwidthPx_label \
   -relief $RELIEF_label_lo

text .fRbottom.txtpcnt \
   -height 1 \
   -width 11 \
   -wrap none \
   -font fontTEMP_text \
   -bd $BDwidth_text \
   -relief $RELIEF_numtext \
   -bg $textBKGD

## Pack the widgets in frame '.fRbottom'.

pack .fRbottom.butReturn \
     .fRbottom.butCancel \
     .fRbottom.butTogside \
     .fRbottom.butHelp \
   -side left \
   -anchor center \
   -fill none \
   -expand 0


pack .fRbottom.txthex \
     .fRbottom.labhex \
     .fRbottom.txtpcnt \
     .fRbottom.labpcnt \
   -side right \
   -anchor center \
   -fill none \
   -expand 0


##+#######################################
## END OF MAIN SECTION TO SETUP THE GUI.
## FRAMES AND WIDGETS ARE DEFINED.
##+#######################################

##+#####################################################################
##+#####################################################################
## BINDINGS:  no additional bindings
##+#####################################################################
##+#####################################################################

##+#####################################################################
##+#####################################################################
## DEFINE PROCEDURES:
##    'color_update'           - called by the '-command' option on the
##                               3 RGB 'scale' widgets.
##    'toggle_side'            - called by the 'ToggleSide' button
##    'put_vars'               - called by the 'UseIt' button
##    'popup_msgVarWithScroll' - called by the 'Help' button
##+#####################################################################
##+#####################################################################


##+#####################################################################
## PROCEDURE 'color_update'
##+#####################################################################
## PURPOSE: To set
##             1) the background color of the preview window
##             2) display the hex & percent values of the r-g-b values
##          as any 0-255 slider is changed.
##
## CALLED BY:  the '-command' option of 3 scale widgets:
##               - .fRsliders.fRred.scale
##               - .fRsliders.fRgreen.scale
##               - .fRsliders.fRblue.scale
##+#####################################################################

proc color_update {x} {

   global r255 g255 b255

   set r255   [.fRsliders.fRred.scale   get]
   set g255   [.fRsliders.fRgreen.scale get]
   set b255   [.fRsliders.fRblue.scale  get]

   ## Show the 0-255 RGB values in hex.

   set RGBcolorHex [format "#%02X%02X%02X" $r255 $g255 $b255]
   .fRpreview config -bg $RGBcolorHex

   .fRbottom.txthex delete 1.0 end
   .fRbottom.txthex insert end $RGBcolorHex

   ## Show the 0-255 RGB values in percents.

   set red_pcnt   [expr {$r255  * 100 / 255}]
   set green_pcnt [expr {$g255  * 100 / 255}]
   set blue_pcnt  [expr {$b255  * 100 / 255}]

   # set red_pcnt   [format "%3.0d" $red_pcnt]
   # set green_pcnt [format "%3.0d" $green_pcnt]
   # set blue_pcnt  [format "%3.0d" $blue_pcnt]

   .fRbottom.txtpcnt delete 1.0 end
   .fRbottom.txtpcnt insert end "$red_pcnt $green_pcnt $blue_pcnt"

}
## END of proc 'color_update'


##+#####################################################################
## PROCEDURE 'toggle_side'
##+#####################################################################
## PURPOSE: To switch the sides of the 'sliders' & 'preview' frames
##
## CALLED BY:  the 'ToggleSide' button
##+#####################################################################

proc toggle_side { } {

   global LR_side

   if { "$LR_side" == "left" } {
      set LR_side "right"
   } else {
      set LR_side "left"
   }

   pack forget .fRsliders .fRpreview

   pack .fRsliders \
        .fRpreview \
      -side $LR_side \
      -anchor w \
      -fill both \
      -expand 1

}
## END of proc 'toggle_side'


##+#####################################################################
## PROCEDURE 'put_vars'
##+#####################################################################
 ## PURPOSE: Put an R255, G255, B255 environment-variables-setting
##           string to standard output.
##
## CALLED BY:  the 'UseIt' button
##+#####################################################################

proc put_vars { } {

   global r255 g255 b255

   set COLORhex [format "%02X%02X%02X" $r255 $g255 $b255]

   #OLD    puts "R255=\"$r255\" ; G255=\"$g255\" ; B255=\"$b255\""

   puts "$r255 $g255 $b255 $COLORhex"

   ## Close the GUI after putting the string to stdout.

   exit

}
## END of proc  'puts_vars'


##+########################################################################
## PROC 'popup_msgVarWithScroll'
##+########################################################################
## PURPOSE: Report help or error conditions to the user.
##
##       We do not use focus,grab,tkwait in this proc,
##       because we use it to show help when the GUI is idle,
##       and we may want the user to be able to keep the Help
##       window open while doing some other things with the GUI
##       such as putting a filename in the filename entry field
##       or clicking on a radiobutton.
##
##       For a similar proc with focus-grab-tkwait added,
##       see the proc 'popup_msgVarWithScroll_wait' in a
##       3DterrainGeneratorExaminer Tk script.
##
## REFERENCE: page 602 of 'Practical Programming in Tcl and Tk',
##            4th edition, by Welch, Jones, Hobbs.
##
## ARGUMENTS: A toplevel frame name (such as .fRhelp or .fRerrmsg)
##            and a variable holding text (many lines, if needed).
##
## 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_msgVarWithScroll { toplevName 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 $toplevName}
   toplevel  $toplevName

   # wm geometry $toplevName 600x400+100+50

   wm geometry $toplevName +100+50

   wm title     $toplevName "Note"
   # wm title   $toplevName "Note to $env(USER)"

   wm iconname  $toplevName "Note"


   #####################################
   ## In the frame '$toplevName' -
   ## DEFINE THE TEXT WIDGET and
   ## its two scrollbars --- and
   ## DEFINE an OK BUTTON widget.
   #####################################

   if {$VARheight > 10 || $VARwidth > 80} {
      text $toplevName.text \
         -wrap none \
         -font fontTEMP_fixedwidth \
         -width  $VARwidth \
         -height $VARheight \
         -bg "#f0f0f0" \
         -relief raised \
         -bd 2 \
         -yscrollcommand "$toplevName.scrolly set" \
         -xscrollcommand "$toplevName.scrollx set"

      scrollbar $toplevName.scrolly \
         -orient vertical \
         -command "$toplevName.text yview"

      scrollbar $toplevName.scrollx \
         -orient horizontal \
         -command "$toplevName.text xview"
   } else {
      text $toplevName.text \
         -wrap none \
         -font fontTEMP_varwidth \
         -width  $VARwidth \
         -height $VARheight \
         -bg "#f0f0f0" \
         -relief raised \
         -bd 2 
   }

   button $toplevName.butt \
      -text "OK" \
      -font fontTEMP_varwidth  \
      -command  "destroy $toplevName"

   ###############################################
   ## PACK *ALL* the widgets in frame '$toplevName'.
   ###############################################

   ## Pack the bottom button BEFORE the
   ## bottom x-scrollbar widget,

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


   if {$VARheight > 10 || $VARwidth > 80} {
      ## Pack the scrollbars BEFORE the text widget,
      ## so that the text does not monopolize the space.

      pack $toplevName.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 $toplevName.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 $toplevName.text \
         -side top \
         -anchor center \
         -fill both \
         -expand 1
   } else {
      pack $toplevName.text \
         -side top \
         -anchor center \
         -fill both \
         -expand 1
   }


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

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


##+###############################################
## END OF PROCS SECTION.
##+###############################################


set HELPtext "\
\ \ \ ** HELP for the RGB Color Selector GUI utility **

         (a Tk script utility originally for 'Freedom Environment' ---
          alias 'F.E.', alias 'FE' --- subsystems at www.freedomenv.com)

Here's a little HELP on setting colors that you know by name
--- using appropriate RGB values.

Most people know that:
   yellow  = red   + green ; bright-yellow  = 255 255 0 (add some blue  to brighten further)
   magenta = red   + blue  ; bright-magenta = 255 0 255 (add some green to brighten further)
   cyan    = green + blue  ; bright-cyan    = 0 255 255 (add some red   to brighten further)

For some colors, like brown, it is not so obvious which RGB colors to use
to create the color.

Brown is basically lots of red, a medium amount of green, and even less blue.
So a medium brightness brown is about 200 150 100.
In particular, 'sandy brown' is 244 164  96.

X color names and their RGB values are shown by the command 'showrgb'.

Here are some color-names and RGB values for REDDISH colors,
in alphabetic order by name:

brown,sandy     244   164    96
coral1          255   114    86
firebrick       178    34    34
khaki,dark      189   183   107
lavenderblush3  205   193   197
magenta3        205     0   205
maroon1         255    52   179
orange,dark     255   127     0
orchid1         255   131   250
peach puff      255   218   185
pink,deep       255    20   147
pink3           205   145   158
plum            221   160   221
rose,misty,3    205   183   181
salmon1         255   140   105
sienna1         255   130    71
tan1            255   165    79
tomato          255    99    71
violet          238   130   238
wood,burly,3    205   170   125


Here are some names and RGB values for GREENISH colors,
in alphabetic order by name:

aquamarine2     118   238   198
chartreuse      127   255     0
cyan,light      224   255   255
green,lawn      124   252     0
green,lime       50   205    50
green,pale      152   251   152
green,sea,1      84   255   159
green,spring      0   255   127
honeydew        240   255   240
mint cream      245   255   250
olivedrab2      179   238    58
turquoise        64   224   208


Here are some names and RGB values for BLUISH colors,
in alphabetic order by name:

azure2          224   238   238
blue,cornflower 100   149   237
blue,dodger      30   144   255
blue,midnight    25    25   112
lavender        230   230   250
lightblue2      178   223   238
purple1         155    48   255
royalblue1       72   118   255
skyblue1        135   206   255
steelblue1       99   184   255
slateblue1      131   111   255
turquoise1        0   245   255
turquoise,pale  175   238   238

Of course, you can scale the RGB values down to get
darker colors. And you can scale the RGB values up
to get brighter colors.
"

##+###############################################
## ADDITONAL GUI INITIALIZATION.
##+###############################################

## No additional GUI initialization, beyond
## setting the 'HELPtext' variable, above.


I hope that some Tcl-Tk 'newbies' can learn from this useful script, just as I learned a lot from its predecessor script --- thanks to some (unknown to me) computer science professor/student at an Australian University half-way around the world from me --- me sitting at an SGI/IRIX (Unix) workstation in the eastern United States back in the late 1990's.


RLE (2012-08-06): Were you aware of the tk_chooseColor script which ships with Tcl/Tk?


uniquename 2012aug14:

RLE, I am formulating a reply. I plan to post it here within the next few days. In the mean time, here is a relatively short reply.

There are a lot of factors involved, leading to making my own color selector, rather than using 'tk_chooseColor'. Briefly, I had forgotten about it --- I saw an image of the GUI about 7 years ago on a web page. In any case, the situation is similar to the search for the ideal font selector utility, which I discuss on my new YAFSG - Yet Another Font Selector GUI page. Everyone has their idea of an ideal selector, and very few have the same ideal.

In the course of looking for info on 'tk_chooseColor', I found some info that suggests a reasonable, but not definite, answer to the question "Which came first --- tk_chooseColor or the script I found at USQ?" I found an email from Ousterhout, dated in 1996, announcing the availability of 'tk_chooseColor'. I found the USQ script a few years later, in 1999. So 'tk_chooseColor' may be the egg, and the USQ script may be the chicken.

Also, I have a reasonable, but not definite, answer to the question "What may have motivated creation of the USQ script?" I believe that a professor (or student) at USQ may have felt, like I, that 'tk_chooseColor' could use a little simplification --- or maybe the simplification made a good exercise for a computer science class.


uniquename 2012aug17:

I found the following image of the tk_chooseColor GUI at the tkdocs.com site --- showing the GUI for 3 different 'platforms' --- Mac OS X and MS Windows and Linux.

tk_chooseColor_MacOSX_MSwin_Linux_784x319.png

I was surprised to see how different the GUI looks on the three platforms. I had always assumed that when a Tk chooser utility (like a file chooser utility) is ported to the different platforms, that the GUI would have the same features on each platform.

In any case, this image shows what I mean by 'obfuscation' in color selector GUI's. With most GUI's like these, when I bring them up, I cannot use them immediately.

It takes me several minutes (or more) to figure out which features are going to be most useful to me --- and how to use them.

There is a lot of 'obfuscation' in the Mac and MS color chooser GUI's --- lots of distracting/time-consuming features.

At first glance, the Linux color chooser looks 'unobfuscated'. But I tried it out on one of my Linux computers by opening a terminal window, typing 'wish', and then typing 'tk_chooseColor'.

I found it works a lot like the color chooser that I presented above (although I have a lot more capability to change fonts and colors to match other GUI's in my software --- using font and color variables and font and color changing utilities of my software systems.)

But then I noticed a distraction --- the color gradients. To me, it would be 'natural' if the color gradients above the red, green, and blue 'scale' widgets were red, green, and blue --- in particular, if they went from

- black (0,0,0) to red (255,0,0)
- black (0,0,0) to green (0,255,0)
- black (0,0,0) to blue (0,0,255)

It took me at least 30 seconds (maybe more than a minute) to figure out why the color gradients are as they are --- and why they seem to be made up of tiny rectangular patches.

I finally realized that the colors on each color-bar are an indication of what color would show up in the color swatch if the slider for that particular bar were moved to line up with that particular color shade.

And, I guess that the gradients are approximated with small rectangles of solid color because it is faster to draw about 16 colored rectangles than to draw in about 256 colored lines graduating through the colors that would appear on the color swatch.

I think these color choosers would be a good way to measure the IQ of a person. You can tell that my IQ is probably less than 130, because it took me about a minute to figure out what the color gradients on the 3 graduated-color bars mean.

A Mensa member or a person with an IQ above 150 probably would have figured it out in less than 15 seconds.

In summary, I think the 3 color choosers above are good for testing people's IQ --- but I don't think they are good as color choosers.


RLE (2012-08-17): The answer to your first implied question (why do the chooser GUI's look different across platforms) is because Tk uses the native system color chooser if there is a native system chooser. So the Mac and Windows choosers are the native ones provided by MacOS and Windows respectively.

X11 on Unix provides no such native widget, so Unix Tk includes a Tk script which generates a color chooser from Tk widgets. The Tk Unix chooser is the one that is most similar to your code above in this page.

I also understand what you mean by "unobfuscated color chooser" now. At first I thought you were referring to the code that implemented the chooser, but you are referring to the complexity of the UI presented by the chooser, not to the code implementing it.


uniquename - 2012sep06

RLE, thanks for explaining why the Mac and MS Windows 'tk_chooseColor' GUI's are so different from the implementation on Linux.

And thanks for bringing up 'tk_chooseColor' in the first place. It has caused me to think of what I could add to my color chooser to help the user choose colors.

I have pointed out that I find the color gradients above the red, green, and blue 'scale' widgets on the Linux version of 'tk_chooseColor' to be more confusing than helpful.

But there is another reason (besides wasting time) that I find it unhelpful --- I am partially red-green blind. Colors like light-green and light-pink look almost gray or white to me. And some shades of green look more like tan or brown --- or I would be hard-pressed to say what color they are.

And because of my condition, I am led to think of how a totally color-blind person might react to the color gradients on the GUI. Such persons would probably find the gradients almost totally useless. They would just look like shades of gray --- on all 3 gradient bars.

But a color-blind person might find some textual info helpful --- kind of like the info seen by running the 'showrgb' command on Linux. That output gives the user color names and the RGB values (0-255) that go with the names. Thus a color-blind person could know where to locate the 3 sliderbars of the 'scale' widgets to get the color 'brown', say.

In fact, one of the first uses of my color chooser was in my 'feAppMenus' and 'feHandyTools' systems --- to choose a color for the toolchests that would go pretty well with the brownish-orangish screen background of Ubuntu 9.10 (2009 October release, 'Karmic Koala').

I had no idea what proportions of RGB to use to get brown. By running 'showrgb', I was able to determine I could get a pretty good color by using a high value for Red, a medium value for Green, and a low value for Blue.

The point I am getting to is that I should add a 'Help' button to my color chooser --- next to the 'TogSide' button. That button will show/hide a scrolling-text-widget that shows some helpful verbiage --- based on 'showrgb' output --- that can help users --- especially vision-challenged users --- help them compose some of the 'hard to concoct' colors.

Most people know that you get yellow from mixing red and green, with essentially no blue (except to brighten the yellow). Similarly, most people know how to get magenta (red-blue) and cyan (green-blue).

But for colors like brown, chartreuse, puce, etc., they could probably use some verbal help.

So I will probably update the code posted above with an implementation of a 'Help' button --- sometime within the next year.

___

uniquename 2012oct28 UPDATE

I added the 'Help' button. The code that was above has been replaced. The new code includes the following changes:

  • Help text was added, along with a proc that shows the text in a popup window with scrollbars.
  • Comments were re-organized and improved --- and it was noted in the comments that this is a 'stand-alone' script that was converted from a script that used 'source' statements to incorporate 'common' code from some Tk 'include' files.
  • Indenting was improved to a more consistent format, and some white-space at the start of many widget-definition and widget-packing lines was removed.
  • Braces were added to 'expr' statements.
  • The font setting section was compacted somewhat.
  • The initial part of the code was re-organized somewhat to follow the 'canonical' format that I use in most of the other Tk scripts that I have posted here. That format is described on the page titled A Canonical Structure for Tk Code --- and variations.

___

uniquename 2014mar13 UPDATE

It has been about a year and a half since my last update to this utility. Since I use (and refer to) this utility in more than 20 different code contributions on this wiki, I think it is worth taking the time to make a few improvements:

1) I added an 'aRtext' array to hold text for labels, buttons, and other widgets of the GUI. In mid-2013, I started doing this in all my Tk code contributions on this wiki. This makes it easier for people to 'internationalize' this script. Most of the text-setting is done in one section near the top of the script.

2) I added some relief, borderwidth, and padding parameters to widget definition statements --- to facilitate experiments in changing/improving the appearance of the GUI.

3) I changed the '-relief' parameter for the two text widgets that hold the RGB values in percents and in hex --- from "raised" to "ridge" --- so that the two text widgets do not look like buttons to be clicked.

I replaced the code above with code containing these changes.


dzach - 2012-10-22 There is this color blindness simulator called "Color Oracle", http://colororacle.org . I find it quite useful when deciding what colors to use in presentations etc.


slebetman - 2012-10-23 05:54:05

Actually, for your use case the Mac style color wheel is more useful. Provided you understand color theory. You can be color blind and it would still be useful as it can be used to answer so many questions that the other two color pickers can't.

First, basic color wheel: as you mentioned, everyone should know the primary and secondary colors: red, yellow, blue + green, orange, purple. Most learn this in elementary school. It actually still works in the RGB space but we just need to modify it a bit. The Mac style color wheel actually works with reflective (red,yellow,blue) and transmissive (reg,green,blue) colors simultaneously. We just need to modify our elementary school knowledge a bit.

We start with printed colors. So we rename red as magenta, rename blue as cyan and let yellow be itself. Why do this? It turns out that red is not really a primary reflective color since we can get red by mixing magenta with yellow. Cyan is blue. It's sort of sky blue. It's just a fancy name for a specific kind of blue. It just turns out that you can derive lots of other kinds of blue from cyan by mixing in red, yellow and black. So that's the very basic. It still looks like our elementary school color wheel, we've just renamed things around a bit.

Now we start mixing. In elementary school you learn that red+blue=purple. Well, actually, magenta+cyan=something bluish. So let's call it blue for convenience: magenta+cyan=blue. As mentioned before, magenta+yellow=red. And finally the traditional yellow+cyan=green. Now we get the Mac style color wheel. Notice something? We started with printed colors CMY and when we mixed them to get secondary colors we ended up with RGB! So, CMY and RGB are really one and the same color wheel. Just rotated 60 degrees.

One of the interesting aspect of this color wheel is that it also shows you how to get the color you want by subtracting its opposite. Look at the wheel. You'll notice that yellow is the opposite of blue. The technical term is complimentary colors. If you take any color and slowly subtract yellow from it you'll notice that the resulting color becomes more and more bluish. The opposite is true, subtract blue from a color and the resulting color is yellowish. You can use this knowledge to manipulate yellows in RGB space since you can only play with red, green and blue sliders. The same can be applied for all the other combinations - remove magenta and you end up with something greenish. Remove red and you end up with something cyanish. If you have a deep enough understanding of this you can even directly design colors in the six digit hex format. For example #cccc00 is obviously yellow due to the lack of blue. Of course, with the wheel GUI you can simply click on the correct coordinates.

Now brown is a special case since real-world brown disagrees with on-screen brown. In the real-world you get brown by mixing red,yellow and blue.. sorry, magenta,yellow and cyan. But it doesn't work on-screen since doing that you'd get various shades of grey or white. You see, organic pigments in the real world are tinged slightly yellowish due to either chemical reaction or impurities. So when you try to mix CMY in the real world to create grey you'd get brown instead. This gives us a clue of where brownish colors lies in the color wheel. It is in the middle near the whites but slightly off towards the reds and yellows. Browns are essentially just desaturated kind of yellows or orange.

All other fancy names of colors are just fancy names of blues or reds or yellows or greens or purples (which btw is blue+magenta) and should be obvious where they'd belong in the color wheel. Brown is the only non-obvious color.

Anyway, this is slightly off-topic but useful if you find yourself trying to figure out colors. Also, this is a very simplified version of color theory and is not 100% accurate. It's just the best practical understanding of color theory I've found to date.