FE 'tkGooie' Utilities

'MATHtools' group

Body Mass Index

(where height may be
entered in inches,
centimeters, or meters
--- and weight may be
entered in pounds
or kilograms)
(FE = Freedom Environment)

The GUI interface of the
Body Mass Index (BMI)
calculator utility.

Large, hi-res image is below.

FE Home Page > FE Downloads Page >

FE 'tkGooies' Description Page >

FE 'tkGooies' 'MATHtools' Menu >

This 'tkBMIcalc' tkGooie code Page

Tcl-Tk code for Tk-GUI

In 2017, I ran across a couple of short articles on BMI (Body Mass Index) which included instructions on how to do the simple calculation of BMI from a person's height and weight --- in inches and pounds.

    The formula for calculating the BMI is given by

    BMI = (704.5 * POUNDS) / (INCHES * INCHES)

    One article gave the coefficient as 703, the other gave 704.5. I decided to use 704.5.

I decided that this would make a nice little Tk GUI script --- where I could include the option of presenting some dietary advice depending on the outcome of the BMI calculation.

Furthermore, I could allow the GUI to pass the output (BMI index) and the inputs (height and weight) from the script to 'stdout'.

This would allow this script to be called from other 'apps' --- such as shell scripts or other Tcl-Tk scripts --- to get those numbers for use in the calling 'app'.

I decided to keep the GUI rather compact by using two 'entry' widgets for entering the height and weight --- rather than using a couple of 'scale' (slider-bar) widgets.

    I may someday provide an alternate GUI using 'scale' widgets instead of 'entry' widgets.

    I have plenty of 'converter' and 'selector' code to use as a starting point,

    An example of a 'scale' widget utility:

    In 2016, I wrote the


    utility to convert between decimal-degrees and degrees-minutes-seconds.

    I could use some of the code from that script to (relatively) quickly make a 'scale' widget version of the BMI calculator.

For the 'entry'-widgets GUI, I need to use an 'edit_inputs' proc to check on numeric values that a user puts in the height and weight 'entry' widgets.

For that, I could modify some numeric-edit procs I used in Tk GUI scripts such as a


utility in the 'MAPtools' group, that I wrote in 2016.

    One of the advantages of using 'scale' widgets (or 'spinboxes' or some equivalent) instead of 'entry' widgets is there is no need for an 'edit_inputs' proc.

    The values returned by 'scale' widgets are always numeric. There is no chance the user will enter 'garbage' characters.


Following a Tk GUI design procedure that I started using around 2015, I laid out a 'text-sketch' of a proposed layout for the GUI.

In the below sketch of the GUI:

  SQUARE BRACKETS indicate a comment (not to be placed on the GUI).
  BRACES          indicate a Tk 'button' widget.
  A COLON         indicates that the text before the colon is on a 'label' widget.

  <----O---->     would indicate a horizontal Tk 'scale' widget (if any).
  UNDERSCORES     would indicate a Tk 'entry' widget (if any).
  CAPITAL-O       would indicates a Tk 'radiobutton' widget (if any).
  CAPITAL-X       would indicates a Tk 'checkbutton' widget (if any).

  The options available to the user are indicated by
  the following 'sketch' of the GUI:

             tkBMIcalc ... calculate Body Mass Index
             [window title]
.fRbuttons   {UseIt} {Exit} {Help} {Calc}
.fRheight    Height: ______  O centimeters    O inches   O meters
.fRweight    Weight: ______  O kilograms   O pounds
.fRbmi       BMI: [text widget goes here]
.fRadvice    Advice:
             [multi-line text widget goes here]

GUI components:

From the GUI 'sketch' above, it is seen that the GUI consists of about

  • 4 button widgets
  • 4 label widgets
  • 2 entry widgets
  • 5 radiobutton widgets (in 2 groups)
  • 2 text widgets
  • 0 checkbutton widgets
  • 0 scale widgets
  • 0 listbox widgets
  • 0 canvas widgets


I set to work converting the code from a couple of converter/selector GUI's to this proposed GUI, and I ended up with the GUI seen in the following image.

This is the GUI as it appears on startup --- the height units-of-measure (radiobuttons) are set to 'inches' and the weight units-of-measure (radiobuttons) are set to 'pounds'.

The height and weight values are set to relatively healthy values --- 70 inches (5 feet 10 inches) and 170 pounds.

    These initial values can be easily changed by changing some 'set' statements at the bottom of the script, in the 'Additional GUI Initialization' section.

At this point, the user can simply change the height and/or weight entries (and the radiobutton settings if one wishes to use metric units), and click on the 'Calc' button to see the new BMI value.


If the user chooses metric units for height, the value in the height entry field is converted to inches when the 'Calc' button is pressed.

If the user chooses metric units for weight, the value in the weight entry field is converted to pounds when the 'Calc' button is pressed.

Then the formula presented near the top of this page is used to perform the BMI calculation.


I put the BMI calculated value and the 'advice' in 'text' widgets rather than 'label' widgets so that the user can copy-and-paste that text from this GUI window to another window (like a text-editor or word-processor window) on the user's desktop.


The message ('advice') area on the GUI gives the user advice on what to do depending on the range in which the BMI value falls.

The standard advice is

  • BMI less than 25.0 is a healthy value

  • BMI between 25 and 30 indicates the person is nearing obesity (over-weight)

  • BMI greater than 30 indicates the person is obese

The following two images show the GUI's advice for the latter two cases.

On leaving the height set at 70 inches and boosting the weight to 190 pounds, a click on the 'Calc' button yielded the following GUI.

On leaving the height set at 70 inches and boosting the weight to 210 pounds, a click on the 'Calc' button yielded the following GUI.

The 'Selector' function of this utility:

If this calculator-selector utility is embedded in another 'app', such as a shell script or another Tcl-Tk script, the 'UseIt' button can be clicked to send the BMI index and the height and weight (in inches and pounds) to 'stdout' --- so that the calling script can use the calculated data and/or the input data.

An example of how the 'stdout' text can be captured in a script variable is shown in comments near the top of some of the 'tkGooies' scripts --- such as the script for the



Built-in Help

The 'Help' button on the GUI provides pretty complete and detailed help for using the GUI.

A proc named 'popup_msgVarWithScroll' presents the Help text in a popup window.

Anyone who implements this script can easily change the Help text, which is defined in a 'set' statement near the bottom of the script.


Below, I provide the Tk script code for this 'tkBMIcalc' utility.

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,

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

  2) Define & pack all widgets in the frames, frame by frame.
              Within each frame, define ALL the widgets.
              Then pack the widgets.

  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 Tk coding 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 from other scripts (code re-use).

I call your attention to step-zero.

One new thing that I started doing around 2014 is using a text-array variable --- named 'aRtext' --- for text in labels, buttons, and other widgets in the GUI.

This can make it easier for people to internationalize my scripts.

I will be using a text-array like this in most of my scripts in the future.

All the 'set' statements for the text array, 'aRtext', are in one contiguous section toward the top of the code.

Experimenting with the GUI

As in all my scripts that use the 'pack' geometry manager (which is all of my 100-plus Tk 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.

That helps me when I am initially testing the behavior of a GUI (the various widgets within it) as I resize the main window.

In this particular GUI, I have chosen to fix the y-size of the GUI window, but allow the x-size to vary --- by using the statement

wm resizable . 1 0

I used '-fill x' and '-expand 1' for the two entry fields so that those fields will expand if the user x-expands the GUI window.

    (I do not foresee using this capability. This just demonstrates a combination of window and widget expansion options when this GUI window is resized.)

If you think the GUI window will be usable in all cases with a fixed size, you could use the statement

wm resizable . 0 0

to keep the window fixed at its initial size.

With the window resizable, you can experiment with the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various frames and widgets --- to get the widget behavior that you want.


Additional experimentation with the GUI:

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.

Some features in the code

There are plenty of comments in the code, to describe what most of the code-sections are doing.

You can look at the top of the PROCS section of the code to see a list of the procs used in this script, along with brief descriptions of how they are called and what they do.

Here is a quick view of how each of the procs are 'triggered'.

  'calc_bmi'                - called by the 'Calc' button.

  'edit_inputs'             - called by the 'calc_bmi' proc.

  'decimal_check'           - called by the 'edit_inputs' proc.

  'put_vars'                - called by the 'UseIt' button.

  'popup_msgVarWithScroll'  - called by 'Help' button to show 'HELPtext' var and
                              to present error messages from the 'edit_inputs' proc.

Comments in the Code

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, potential young Tcler's might be tempted to return to their iPhones and iPads (and other equivalents) --- to surf the web looking for the latest news about 'Brangelina' (Brad Pitt and Angelina Jolie) and other 'supercouples'.

The Tcl-Tk script CODE

Here is a link to CODE for the script 'tkBMIcalc.tk'.

With your web browser, you can 'right-click' on this link --- and in the menu that pops up, select an item like 'Save Link Target As ...' --- to save this file to your local computer.

Then you can rename the file to remove the '.txt' suffix. Make sure that you have execute permission set on the file --- in order to execute the script.

Here is a 2017 September image of the 'tkGooies' 'MATHtools' toolchest --- showing the new 'tkBMIcalc' drawer of the toolchest.


I mentioned above the option of changing the 'tkBMIcalc' GUI to use 'scale' widgets (or 'spinbox' widgets --- or the equivalent done with an 'entry' widget and a couple of tiny 'button' widgets) --- instead of using 'entry' widgets for the two numeric values.

The only other potential enhancement that comes to my mind at this point:

  • Add more advice for extremely large BMI values

    At large BMI values --- say, larger than 40 and larger than 50 --- it might be advisable to add even more advice.

    For example, advice concerning getting a blood test for level of tri-glycerides, and information on what various triglyceride levels suggest.

If I ever find that I am using this utility and I find that any of the features above are highly advisable to add or implement, then I may return to this script to provide that feature or alternate implementation.


As I have said on other Tcl-Tk code-donation pages on this site ...

There's a lot to like about a utility that is 'free freedom' --- that is, no-cost and open-source so that you can modify/enhance/fix it without having to wait for someone else to do it for you (which may be never).

A BIG THANK YOU to Ousterhout for starting Tcl-Tk, and a BIG THANK YOU to the Tcl-Tk developers and maintainers who have kept the simply MAH-velous 'wish' interpreter going.

Bottom of this web page for
presenting Tcl-Tk code for a
tkBMIcalc 'app'
--- a utility in the FE 'tkGooies' system,
in the 'MATHtools' group.

To return to a previously visited web page location, click on the Back button of your web browser a sufficient number of times. OR, use the History-list option of your web browser.
OR ...

< Go to Top of Page, above. >

Page history:

This FE web page was created 2017 Aug 22.

Page was changed 2017 Sep 24.
(Added an image of the 'MATHtools' toolchest.)

Page was changed 2019 Mar 07.
(Added css and javascript to try to handle text-size for smartphones, esp. in portrait orientation.)

Page was changed 2019 Jul 01.
(Specified image widths in percents to size the images according to width of the browser window.)

This code and description has NOT been posted on a Tcler's Wiki page --- at wiki.tcl-lang.org --- formerly wiki.tcl.tk. If I ever do so, as a backup and alternative to this page, I plan to add a link to that Wiki page here.