![]() |
Welcome to Beginner Programming
|
| Course content | Enter chat room | Send email
to mailing list |
Check calendar |
In this lesson we are going to learn how to extend and create our own Tcl/Tk commands. We are going to learn about some program control statements and constructs.
Any computer language contains a relatively small set of basic commands. If that is all that it could do it would not be very useful or practical. It would be better if one could extend existing commands or create entirely new ones as we needed them. Fortunately Tcl/Tk has just that capability.
Before we begin we need to discuss and reinforce the relationship between
the "wish" program and our little programs. Tcl/Tk is what is known
as an "interpreted language". What this really means is that
the statements in our little programs are "digested" one by one inside
the "wish" program as they execute. This has no real impact
on what we are learning except that phases such as "Tcl/Tk interpreter"
or "interpreted by wish" etc. will appear in the lessons such as this one.
Suffice to remember that our programs require wish in order to run.
| HINTS:
Remember the time saving "tiling" hint from lesson #2. ie. open your Wish program and editor program and position the resulting three windows in such a way that there is no overlap. It is probably a good idea to print this lesson off and work from the printout ... otherwise you are going to have more clutter on your screen. |
Step 1: first example |
| #=======================================
# iCanProgram.com # Lesson#3: first example #======================================= #=======================================
puts stdout [format "lastcolor was %s" $mycolor] return $mycolor
#========================================
button .hello -text "change me to green" -background red \
|
The first thing you will notice is the statements which begin with the "#" character. The Tcl/Tk interpreter program (eg. wish) will simply ignore these statements. This type of statement is used to add some description to a computer program. As such these statements are often referred to as "comments". In addition blank lines are ignored as well with one important exception noted below.
Occasionally Tcl/Tk statements get very long. Long statements
are very difficult to read because a portion of those long lines is often
"off the visible screen". To make long statements more readable
Tcl/Tk has assigned the "\" character a special significance.
It is often referred to as the "continuation" character.
What the "\" tells the wish program is that the line that follows is really
to be treated as part of the same line that the "\" appears on.
As such you can not follow a line ending in "\" with a blank line.
In the example above we have used the continuation character to divide
this line into two lines:
| button .hello -text "change me to green" -background red -command {set lastcolor [hogwarts $lastcolor]} |
Notice that we have also introduced another argument for the button widget. This argument is the "-command" argument. It is probably the single most powerful feature of the Tk part of the Tcl/Tk language. What we are saying is "whenever you press the button with the mouse jump and execute the statement enclosed by the {} immediately following the -command argument". This is what allows Tk programs to actually interact with us humans.
Before we try to understand the -command we have for our button we need
to understand a couple of other new Tcl/Tk ideas. The
first of these is what is called a variable. Computer
programs, like calculators, would be a lot less useful if we could not
store values for later use. The mechanism for storing
values is to create a named storage area called a variable. In Tcl/Tk
we do this by using the "set" command. An example in our code is:
| set lastcolor red |
In this example our variable is named "lastcolor" and the value we are
assigned to that variable is "red". We can then use that
stored value at other places in our program by adding a "$" symbol to the
front of the variable name. You can see a couple of examples
of this in the program example above. The most interesting
of these statements also merits further explaination:
| puts stdout [format "lastcolor was %s" $mycolor] |
In this statement we have introduced the first of our "statement within
a statement" constructs. The inside statement is enclosed in
"[]". The way the wish program handles this is that it
first executes the inside statement. In this case:
| format "lastcolor was %s" $mycolor |
As with any Tcl/Tk statement this produces a result. The wish program then executes the outer statement
puts stdout "whatever the result was from the format statement"
Compound statements, as these are sometimes called, are very important Tcl/Tk constructs to understand. We will be encountering these many times in future lessons. The format statement itself is a very powerful and important Tcl/Tk statement. The format statement can be viewed as a kind of "text creation statement". It is often desirable in a computer program to display the result of a computation or the value stored in a variable as part of a human friendly phrase. For this purpose we use the Tcl/Tk format statement. If you examine the 1st argument to the format statement:
"lastcolor was %s"
You can readily identify a portion of the "human friendly" phase. In this case it would be "lastcolor was". We would like to be able to finish this phase using the contents of the variable that we called "mycolor". We do this by using a special format character called a placeholder. In this case it is "%s". The format statement understands a whole range of placeholder types. The "%s" means that "the variable I'm holding the place for is a text string". The third argument in our format statement identifies the variable value that we wish to have stuffed into the spot held open by the placeholder. In our case that is:
$mycolor
The resulting phase in our example might be something like:
lastcolor was red
if the value stored in "mycolor" variable was in fact "red".
We now have talked about all the new Tcl/Tk constructs in our little
program example with the exception of the statement:
| proc hogwarts { mycolor } { |
The command "proc" in this statement is informing the wish interpreter
program that we want to create our very own new Tcl/Tk command.
In this case we are calling our new Tcl/Tk command "hogwarts".
The first matching set of {} tell the wish program that our new command
will accept a single argument ... and with our command that argument will
be named "mycolor". The single "{" at the end of the
line denotes the beginning of the block of Tcl/Tk code which will constitute
our new command called hogwarts. This logic will continue
until we encounter the "closing brace" "}" as in:
| } ;# end of proc hogwarts |
We have introduced another form of Tcl/Tk comment here as well. If you want to add a comment to the same line as a Tcl/Tk statement is on you must use two characters ";#" together to denote the beginning of this comment string.
The return statement presents the result that we want our new hogwarts
command to give back or return. In this simple example we are
simply returning the same value that we gave in as an argument.
| return $mycolor |
Everything between the opening brace "{" and the closing brace "}" constitute the logic associated with our new command called hogwarts. In our simple example the puts statement and the return statement are the only statements contained within hogwarts. Our new commands can be as simple or complicated as we need to make them. This capability gives our computer language a huge degree of flexibility and richness. It is as if we can take words in our spoken language and combine them together to create brand new words of our own.
Having defined our new command "hogwarts" we can now have it execute
every time we press the button with the mouse by adding the following to
the "-command" argument:
| set lastcolor [hogwarts $lastcolor] |
Remember how the compound statements execute. Inner part first ... outer part next.
Go ahead and type this program in, save it and execute it as you did in lesson #2. You should see an output that looks something like this.
Step 2: more useful example |
| #=======================================
# iCanProgram.com # Lesson#3: more useful example #======================================= #=======================================
puts stdout [format "lastcolor was %s" $mycolor] if { $mycolor == "red" } {
puts stdout [format "newcolor is %s" $newcolor]
#========================================
button .hello -text "change me to green" -background red \
|
What we have done in this enhanced example is added some new statements to our hogwarts command. The first of those new constructs is what is known as the "if ... then ... else" branching construct. Computers excel at this kind of true or false branching decisions. Most of the so called "intelligence" in computer software can be traced back to statements like these in the code. The "if" statement allows our little program to alter its execution path depending on the contents of a variable.
It begins with the statement:
| if { $mycolor == "red" } { |
In English this reads "if the value stored in our variable we have called
mycolor is equal to red then do this". The "this" in
this case is everything between the last { on the if line and the next
closing }. In our little example this code block includes:
| .hello configure -text "change me to red" -background green
set newcolor green |
Here we have introduced our final Tcl/Tk concept for this lesson ... the ability to alter the attributes on a Tk widget even after it has been drawn on the screen. This is neat stuff. We can alter the color of our button. We can alter the text in our button. We can do all these things based on how we code our program logic and flow. The statement which does all this magic is:
.hello configure ...
Recall that when the button was defined it was given the name ".hello". Thus the .hello configure command construct is saying "I want to change something about the widget I have called .hello ... in this case a button widget". Notice in this example we are changing the text in the button as well as its background color. When this statement executes that is exactly what will happen on the screen.
The other statement inside our "true" branch of our "if" statement simply allows us to remember the new color we have assigned to our button.
The closing } for our "true" branch is found as part of the else statement
below:
| } else { |
This says "I'm done with the "true" branch and I now want to code the "false" branch". This is what "if" statements are all about. If the statement is false it WILL SKIP OVER THE "TRUE" BRANCH and execute the code contained in the "false" branch as denoted by the opening brace { after the else statement. It is hard to see from this very simple example but this is how computers get much of their apparent "intelligence". You can see that it isn't intelligent at all! The intelligence is all supplied by the human programmer in the form of these true and false blocks of code.
Our false branch in our code simply mirrors the true branch in that we will alter the text and color to reflect a "red" button and remember that color in our "newcolor" variable.
.hello configure -text "change me to green" -background red
set newcolor red
The false branch block is ended by the single closing } as below
} ;#end if else
If you now type in this program and run it you should see the button
toggle between red and green each time you click on it with your mouse.
Summary |
![]() |
Congratulations! You have completed the toughest lesson of the bunch. Computer languages are not all dry and boring like this stuff is. Unfortunately, you need to understand this to go forward to the interesting stuff like ... games. |
You have been introduced to a bunch of new Tcl/Tk statements and constructs in this lesson. Let's review:
Exercises |
End of Lesson 3.