|
TCL
TCL is a script language, like PERL. TCL is avalaible for UNIX, Windows, even Machintosh.
puts "words";
puts (words};
set string "toto";
puts $string;
puts "this is $string"
|
words
(words}
toto
this is toto
|
set a "1";
set b "2";
puts "a=$a and b=$b";
set X [expr $a + $b];
puts "$X";
set X [expr 5+2];
puts "$X";
|
a=1 and b=2
3
7
|
set x "toto";
switch $x \
"ONE" "puts ONE=1" \
"TWO" "puts TWO=2" \
"default" "puts NO_MATCH";
|
NO_MATCH |
set x "toto";
switch $x \
"ONE" "puts ONE=1" \
"TWO" "puts TWO=2" \
"toto" "puts MATCH" \
"default" "puts NO_MATCH";
|
MATCH |
set x "1";
if {$x == 1} \
then \
{ \
puts "x=1"; \
} else { \
puts "x!=1"; \
}
|
x=1
|
set x "0";
while {$x < 10} \
{ \
puts "x = $x"; \
set x [expr $x+1]; \
}
|
x = 0
x = 1
x = 2
x = 3
x = 4
x = 5
x = 6
x = 7
x = 8
x = 9 |
for { set i "0"; } {$i < 10} {set i [expr $i+1];} \
{ puts "$i"; };
for { set i "0"; } {$i < 10} { incr i; } \
{ puts "$i"; };
|
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
|
proc toto {a b} \
{ \
set x [expr $a+$b]; \
return $x; \
};
set y [toto "33" "20"];
puts "$y";
|
53 |
proc toto { first args } \
{ \
puts "args = $args"; \
puts "first = $first"; \
};
puts "[toto a b c d]";
|
args means "variable number of arguments".
args = b c d
first = a |
proc toto { {first "11"} } \
{ \
puts "first = $first"; \
};
puts "[toto]";
puts "[toto 10]";
|
The {...} means "default value".
first = 11
first = 10 |
proc toto { x y } \
{ \
upvar $x pointer1 $y pointer2; \
set pointer1 "10"; \
set pointer2 "20"; \
};
proc print {} \
{ \
set y "22"; \
set z "12"; \
puts "y=$y z=$z"; \
toto y z; \
puts "y=$y z=$z"; \
}
print;
|
upvar $x var means that 'x' can be see as a C pointer.
y=22 z=12
y=10 z=20
|
set tab {a b c d};
set x [lindex $tab 2];
puts "$x";
|
lindex $tab 2 means "return the element that index is 2".
c |
set tab [split "el1.el2.el3" "."];
set x [lindex $tab 2];
puts "$x";
puts "[lindex $tab 1]";
|
split takes the string "el1.el2.el3" and extracts each elements separated by a ".". So the
string "el1.el2.el3" returns the list {el1 el2 el3}.
el3
el2 |
set tab [list "el1_" "el2_" "el3_"];
set x [lindex $tab 2];
puts "$x";
puts "[lindex $tab 1]";
|
list just creates a list.
el3_
el2_ |
set tab [list "el1_" "el2_" "el3_"];
set n "0";
foreach i $tab \
{ \
puts "$n: $i"; \
incr n; \
};
|
foreach takes each item of a list, one at the time.
0: el1_
1: el2_
2: el3_ |
set list1 [list a b c d];
set list2 [list "e1" "e2" "e3" "e4"];
set list3 [concat $list1 $list2];
puts "list3 = $list3";
|
list3 = a b c d e1 e2 e3 e4 |
set list3 [list a b c d "e1" "e2" "e3" "e4"];
lappend list3 {1 2} "toto"
puts "list3 = $list3";
|
list3 = a b c d e1 e2 e3 e4 {1 2} toto |
set list3 [list a b c d "e1" "e2" "e3" "e4" {1 2} "toto"];
set list4 [lreplace $list3 8 9 "el8" "el9"];
puts "list4 = $list4";
|
list4 = a b c d e1 e2 e3 e4 el8 el9 |
set list3 [list a b c d "e1" "e2" "e3" "e4" {1 2} "toto"];
set list5 [linsert $list3 4 "elem1 elem2"];
puts "list5 = $list5";
|
list5 = a b c d {elem1 elem2} e1 e2 e3 e4 {1 2} toto |
set list1 [list {toto est la} "e2" "e3" "e4"];
set zz [lsearch $list1 toto*];
puts "index of \"toto*\" = $zz";
puts "list1\[$zz\] = [lindex $list1 $zz]";
|
index of "toto*" = 0
list1[0] = toto est la |
set list1 [list {toto est la} "e2" "e3" "e4"];
set sorted [lsort $list1];
puts "$sorted";
|
e2 e3 e4 {toto est la} |
set list1 [list {toto est la} "e2" "e3" "e4"];
set cutted [lrange $list1 1 3];
puts "$cutted";
|
e2 e3 e4
|
set chaine "my string";
puts "the size of \"$chaine\" is [string length $chaine]";
puts "the character index 3 of \"$chaine\" is [string index $chaine 3]";
puts "chaine\[3..7\]: [string range $chaine 3 7]";
|
the size of "my string" is 9
the character index 3 of "my string" is s
chaine[3..7]: strin |
set s1 "toto1";
set s2 "toto2";
set s3 "toto2";
if { [string compare $s1 $s2] == 0} \
then \
{ \
puts "\"$s1\" equal \"$s2\""; \
} \
else \
{ \
puts "\"$s1\" not equal \"$s2\""; \
};
if { [string compare $s2 $s3] == 0} \
then \
{ \
puts "\"$s2\" equal \"$s3\""; \
} \
else \
{ \
puts "\"$s2\" not equal \"$s3\""; \
};
|
"toto1" not equal "toto2"
"toto2" equal "toto2" |
set ch "the computer is running for too long now - comp";
set m "comp";
set n [string first $m $ch];
puts "the match \"$m\" appears first at position $n";
|
the match "comp" appears first at position 4 |
set ch "the computer is running for too long now - comp";
set m "comp";
set n [string last $m $ch];
puts "the match \"$m\" appears last at position $n";
|
the match "comp" appears last at position 43 |
set ch "the computer is running for too long now - comp";
set m "comp";
set c [string wordend $ch 5];
puts "The index of the first character after word at index 5 is $c";
|
The index of the first character after word at index 5 is 12 |
set ch "the computer is running for too long now - comp";
set m "comp";
set c [string wordstart $ch 5];
puts "The index of the first character before word at index 5 is $c";
|
The index of the first character before word at index 5 is 4 |
set ch "the computer is running for too long now - comp";
set rc [string match "*computer*" $ch];
puts "rc = $rc";
if {$rc == 1} \
{ \
puts "string ch contains match \"computer\""; \
} \
else \
{ \
puts "string ch not contains match \"computer\""; \
};
|
string ch contains match "computer"
|
Open the file "c:\tmp\toto.txt" in read only mode.
Read the content of the file (and place it into the variable buff).
Then print buff and close the file.
set fd [open "c:/tmp/toto.txt" w];
set buff "exemple d'ecriture";
puts $fd "$buff"
close $fd;
|
Open the file "c:\tmp\toto.txt" in write mode only.
Write the content of the buffer buff into the file.
Then close the file.
|
set fd [open "com2" w];
set buff "exemple d'ecriture";
puts $fd "$buff"
close $fd;
|
com1 and com2 are connected with a null modem. The 2
serial ports have the same configuration (9600/8 bits/none/1 bits/none).
On com1 we open a terminal.
Open serial port "com2".
Write the content of the buffer buff into the port.
Then close the serial port. We can see the data on the terminal. |
set fd [open "com2" w];
fconfigure $fd -mode 9600,n,8,1
set buff "toto";
puts $fd $buff
close $fd;
|
Serial configuration:
- 9600 baud
- parity: none
- 8 bits data
- 1 stop bit
|
set fd [open "com2" r];
fconfigure $fd -mode 9600,n,8,1
set car [read $fd 1];
puts $car;
close $fd;
|
com1 and com2 are connected with a null modem. The 2
serial ports have the same configuration (9600/8 bits/none/1 bits/none).
On com1 we open a terminal.
Open serial port "com2" for reading.
read 1 character from the serial port.
Then close the serial port.
Note: it is very important to give the 2 serial ports the same setting. |
set fd [open "com2" r];
fconfigure $fd -mode 9600,n,8,1
set car "0"
while {$car != "s"} \
{ \
set car [read $fd 1]; \
puts $car; \
}
close $fd;
|
Same but with a "while" loop. |
|
|
Buttons
# global variables
set number "0"
# callback
proc bouton_proc {} \
{ \
global number; \
set number [expr $number + 1]; \
.bouton configure -text "$number"; \
}
# Tk GUI
button .bouton -text "$number" -command bouton_proc
pack .bouton
|
Each time you click on the button, the number value increases by 1. |
Buttons
# global variables
set number "0"
# callbacks
proc bouton_proc {} \
{ \
global number; \
set number [expr $number + 1]; \
.bouton configure -text "$number"; \
}
proc quit_proc {} \
{ \
destroy .button .quit; \
exit 0; \
}
# Tk GUI
button .bouton -text "$number" -command bouton_proc
button .quit -text "quit" -command quit_proc
pack .bouton .quit
|
When you press "quit" the application is destroyed. Note the a call to exit is enough. |
Color image with labels
#callbacks
proc quit_proc {} \
{ \
destroy .baner .quit; \
exit 0; \
}
# Tk GUI
image create photo map -file imag.gif
label .baner -image map
button .quit -text "quit" -command quit_proc
pack .baner .quit
|
|
Color images and labels
# globals
set image_num "0";
#callbacks
proc quit_proc {} \
{ \
destroy .baner .quit .change; \
exit 0; \
}
proc change_proc {} \
{ \
global image_num;
if {$image_num == "0"} \
then \
{ \
.baner configure -image new_map; \
set image_num "1"; \
} \
else \
{ \
.baner configure -image map; \
set image_num "0"; \
} \
}
# Tk GUI
image create photo map -file imag.gif;
image create photo new_map -file new_imag.gif;
label .baner -image map;
button .change -text "change image" -command change_proc;
button .quit -text "quit" -command quit_proc;
pack .baner .quit .change;
|
Each time you click on "change image", you change the image.
|
Color image and canvas
# globals
set image_num "0";
#callbacks
proc quit_proc {} \
{ \
destroy .baner .quit .change; \
exit 0; \
}
proc change_proc {} \
{ \
global image_num; \
if {$image_num == "0"} \
then \
{ \
set image_num "1"; \
.baner delete image_1; \
.baner create image 50 25 -image \
new_map -tag image_2; \
} \
else \
{ \
set image_num "0"; \
.baner delete image_2; \
.baner create image 75 30 -image \
map -tag image_1; \
} \
}
# Images (items for the canvas)
image create photo map -file imag.gif;
image create photo new_map -file new_imag.gif;
# create the canvas and associate the items
# The identifier 'image_1' represents the image 'map'. Identifiers are
# used to access each part of the canvas.
# Note that the "origine" of the image is the center of the image (not
# the upper left coner !).
canvas .baner -width 150 -height 100;
.baner create image 75 30 -image map -tag image_1;
button .change -text "change image" -command change_proc;
button .quit -text "quit" -command quit_proc;
pack .baner .quit .change;
|
When you press the button "change image" the content of the canvas is modified.
|
Interacting with the canvans (moving tags)
# globals
set image_num "0";
set x_line_1 "75";
#callbacks
proc quit_proc {} \
{ \
destroy .baner .quit .change .left . \
exit 0; \
}
proc change_proc {} \
{ \
global image_num; \
if {$image_num == "0"} \
then \
{ \
set image_num "1"; \
.baner delete image_1; \
.baner create image 50 25 -image \
new_map -tag image_2; \
} \
else \
{ \
set image_num "0"; \
.baner delete image_2; \
.baner create image 75 30 -image \
map -tag image_1; \
} \
}
proc left_proc {} \
{ \
global x_line_1;
.baner delete line_1; \
set x_line_1 [expr $x_line_1 + 3]; \
.baner create line $x_line_1 0 \
$x_line_1 60 -smooth on \
-fill black -tag line_1; \
}
# create canvas tags
# - Images items for the canvas
image create photo map -file imag.gif;
image create photo new_map -file new_imag.gif;
# create the canvas and associate the items
# The identifier 'image_1' represents the image 'map'. Identifiers are
# used to access each part of the canvas.
# Note that the "origine" of the image is the center of the image (not
# the upper left coner !).
canvas .baner -width 150 -height 100;
.baner create image 75 30 -image map -tag image_1;
.baner create line 75 0 75 60 -smooth on -fill black -tag line_1
.baner create line 0 30 150 30 -smooth on -fill black -tag line_2
button .change -text "change image" -command change_proc;
button .left -text "left" -command left_proc;
button .quit -text "quit" -command quit_proc;
pack .baner .quit .change .left;
|
Same as previous but when you click on the buuton "left", the vertical line
moves to the left.
|
Background procedure
# globals
set image_num "0";
set x_line_1 "75";
#callbacks
proc quit_proc {} \
{ \
destroy .baner .quit .left . \
exit 0; \
}
proc left_proc {} \
{ \
global x_line_1;
.baner delete line_1; \
set x_line_1 [expr $x_line_1 + 3]; \
.baner create line $x_line_1 0 \
$x_line_1 60 -smooth on \
-fill black -tag line_1; \
after 1000 left_proc; \
}
proc stop_proc {} \
{ \
after cancel left_proc; \
}
# create canvas tags
# - Images items for the canvas
image create photo map -file imag.gif;
# create the canvas and associate the items
# The identifier 'image_1' represents the image 'map'. Identifiers are
# used to access each part of the canvas.
# Note that the "origine" of the image is the center of the image (not
# the upper left coner !).
canvas .baner -width 150 -height 100;
.baner create image 75 30 -image map -tag image_1;
.baner create line 75 0 75 60 -smooth on -fill black -tag line_1
button .left -text "left" -command left_proc;
button .stop -text "stop" -command stop_proc;
button .quit -text "quit" -command quit_proc;
pack .baner .quit .left .stop;
|
When you press "left" the vertical line begins to move to the left and it
keeps going until you press "stop".
|
Scrollbars and geometry managers
# globals
set image_num "0";
#callbacks
proc quit_proc {} \
{ \
destroy .baner \
.quit \
.scroll_y \
.scroll_x \
. \
exit 0; \
}
# Laod map and get properties (used to center the image)
image create photo map -file pays.gif;
set border 20
set max_x [image width map];
set max_y [image height map];
set pos_x [expr $max_x / 2 - [expr $border / 2]];
set pos_y [expr $max_y / 2 - [expr $border / 2]];
set canvas_width [expr $max_x + [expr $border / 2]];
set canvas_height [expr $max_y + [expr $border / 2]];
set Scrolling_Win "-30/-30/$canvas_width/$canvas_height"
# Create scrollbars and apply them to the canvas
scrollbar .scroll_x -command ".baner xview" -orient horizontal;
scrollbar .scroll_y -command ".baner yview" -orient vertical;
canvas .baner -relief sunken -borderwidth 2 \
-width [expr $max_x + 10] \
-height [expr $max_y + 10] \
-scrollregion [split $Scrolling_Win /] \
-xscrollcommand ".scroll_x set" \
-yscrollcommand ".scroll_y set";
# apply the map into the canvas
.baner create image "$pos_x" "$pos_y" -image map -tag image_1;
button .quit -text "quit" -command quit_proc;
label .hauteur -text "$max_x x $max_y";
pack .quit -side bottom;
pack .scroll_y -side right -fill y;
pack .scroll_x -fill x;
pack .hauteur;
pack .baner;
pack .hauteur;
|
|
Serial port and timer
set fd [open "com2" r];
fconfigure $fd -mode 9600,n,8,1
proc quit_proc {} \
{ \
global fd; \
after cancel Read_Com; \
close $fd; \
destroy .text \
.quit \
.screen \
.; \
exit 0;
}
proc Read_Com {} \
{ \
global fd; \
set car "0"; \
set car [read $fd 1]; \
.text configure -text "$car"; \
puts $car; \
update; \
after 1000 Read_Com;
}
button .quit -text "quit" -command quit_proc;
button .text -text "read" -command Read_Com;
label .screen -text "data";
pack .quit .text .screen;
|
com1 and com2 are connected with a
null modem. The 2 serial ports have the
same configuration (9600/8 bits/none/1
bits/none). On com1 we open a terminal.
If you click on "read" it opens the serial port "com2" for reading.
Then it reads 1 character from the serial port every second.
Keep in mind that the serial line is configured in "blocking mode": if
there is no character to read, then the read operation blocks the process.
The "update" command forces the refresh of the screen.
|
|