Pragana's Tcl Guide
Old notes
Skinable tk widgets
"It is tcl/tk code, so it must be ugly". How many times I've
heard people saying that without even complaining. If at least they really
know what they are saying... Well, time to prove they are wrong!
Tcl/tk can help us to build beautiful widgets, and with custom skins, as
many other toolkits. Better yet, in tcl you can write those things with small
code. Do you know what smaller code means? It means less bugs to be fixed,
more maintainability, less time to develop. Let they do in Java or C++ and
fix later. We are going to write it once, small and elegant. We'll write
in tcl :^)
What's in a skin
Let us first explain what is a skin, anyhow. A skin is just a collection
of bitmaps, generally placed together in a single file for economy. We will
borrow skins from Xmms, as there are many of them and I'm too lazy to draw
fancy widgets. We are going to create skinable buttons and later skinable
scales (volume-like controls in tk's nomenclature).
Here is a image of the main Xmms button bar:

Each button is represented twice, first in its normal state, then in the
pressed down state.
We will need to get this image and break it in the several small images that
we will need for our "simulated buttons". Why simulate a button, if tk already
have good customizable buttons? Because with the regular button, we have
no way to change the image when it is pressed down (except by using bindings),
so it is easier to just place the image in a simple label widget.
# Img
is optional, if you want to read .bmp files
package require Img
image create photo btns -file cbuttons.bmp
set btnw 23
set btnh 18
for {set i 0}
{$i < 5} {incr i} {
for {set j 0} {$j < 2} {incr j} {
set img ib${i}_$j
image create photo $img
$img copy btns -from [expr $i * $btnw] [expr $j * $btnh]
\
[expr ($i+1) * $btnw] [expr ($j+1) * $btnh - 1]
}
}
You may need the original cbuttons.bmp
to do it yourself.
What does that code do? It creates lots of images (total of 10), for the
first five buttons we have in our skin. I left out the sixth button as it
is smaller and don't brings much novelty to our reasoning. Each button will
have two images, ib${i}_0
and ib${i}_1,
where ${i} is
in the range 0..4. If you have the Img extension installed, you may read directly
.bmp files, otherwise, you first convert cbuttons.bmp to a .gif file that
may be read by standard tk.
Bind to make your code live
Now let's discuss the bindings needed. When a button is pressed, its image
change to the lower image (in the picture above) and its attached command
is executed.
When the mouse button is released the button simply returns to its normal
state again.
We may create all buttons at once:
frame .bts
for {set i 0} {$i <
5} {incr i} {
label .lb$i -image ib${i}_0 -highlightthickness 0 -border 0
bind .lb$i <ButtonPress-1> \
[list .lb$i config -image ib${i}_1]
bind .lb$i <ButtonRelease-1> \
[list .lb$i config -image ib${i}_0]
pack .lb$i -in .bts -side left
}
Notice we need to set highlightthickness
and border to zero, so the buttons
stack nicely.
How to bind comands to those buttons? Easy. Just remember to begin the binding
with {+
to not replace the default binding, or the button image will not change.
To quick check your nice butttons, insert this binding:
bind all <1>
{+puts "button %W pressed"}
You may now pack .bts where you need it. If you want to
go further and duplicate Xmms' face, add the following code:
image create
photo imain -file main.bmp
frame .main
label .main.lb -image
imain
pack .main.lb
place .bts -in .main
-x 18 -y 90
pack .main
The values -x 18 -y 90 fits the buttons
at the right place in Xmms main frame. Get the main.bmp
image too.

I'm sorry the image above is not a tclet, or you would see how nice those
buttons are.
The images of this skin are from NeXTAmp2.4 by gLaNDix (glandix@linuxfreak.com).
You may grab thousands of skins from Xmms
and Winamp sites. And you now don't have
excuses for making ugly tcl/tk GUIs.
Next time, I'll show you a little more complex example: a skinable tk scale
widget, borrowing more bitmaps from Xmms skins. Don't miss it!
That's all fellows. Happy hacking!
Back Home