R: Creating Graphical User Interfaces (Guis) Using The TCLTK
R: Creating Graphical User Interfaces (Guis) Using The TCLTK
R: Creating Graphical User Interfaces (Guis) Using The TCLTK
Introduction to Tcl
Adrian Waddell
University of Waterloo Departement of Statistics and Actuarial Science
September 8, 2010
Tk and R
Fortunately some understanding of Tcl and its naive Tk extension will be sucient to make use of the tcltk package. This further allows you to make use of the excellent www.tcl.tk web page to get full Tcl/Tk documentation and plenty of examples. The syntax of Tcl diers from that of R quite a lot. The tcltk library provides a whole set of Tk wrapper functions such that the user can integrate GUIs easily in R style into its R source code. Knowing Tcl and native Tk will however help to customize some GUIs for ones own special needs, as they open the door to the complete Tcl/Tk command set. If you want an overview or a rst impression of Tks capability, browse through this web page with examples, maintained by Philippe Grosjean, and also run some of the demos in R:
> library(tcltk) > demo(package = "tcltk") > demo(tkcanvas)
Brent B. Welch kindly gave me the permission to adapt some of his examples (the pack geometry manager) directly for these slides. More advanced Tk programmers might want to take a look at this book.
The Tcl equivalent to the R prompt > is the Tcl shell (tclsh) promt %. R comes with Tcl/Tk by default and provides with the .Tcl function a basic interface between R and Tcl.
> library(tcltk) > .Tcl(puts stdout "Hello World.")
This code example invokes the command puts with the arguments stdout and the character string "Hello World.". Using the Tcl shell instead you can get the same output with the following code:
% puts stdout "Hello World."
Hence, in what follows, all the pure Tcl code can be executed in R by wrapping a .Tcl( and ) around it. You can check which Tcl version your R connects to by entering to R
> .Tcl(puts stdout $tcl_version)
In fact,
puts stdout Hello
would have also worked, as Hello appears to the Tcl interpreter as a single argument. However
puts stdout Hello World
Does not work because the Tcl things that Hello World are two arguments (separated by a white-space).
In the Tcl world, accessing is called variable substitution. Variables are deleted with the unset command
unset x
is used for a nested command. The previous example was an example of a command substitution.
[]
When calling the expr command: put its argument into curly braces {} in order for expr to make all the substitutions in the expression. For example for
expr $x+5*$y
the Tcl interpreter will rst substitute $x+5*$y and pass the string! to the expr command, which in turn has to converse it back to numeric values. Better is to give the unsubstituted string $x+5*$y directly to expr, and let expr do the substitutions. Doing so results in a gain of speed and precision. You can prevent the Tcl interpreter substitutions by putting the arguments in curly braces {}, for example
expr {$x+5*$y}
Grouping
As we saw in some previous examples, we can either use double quotes to group words into one argument,
set x "Farewell, fair cruelty."
or curly braces, with the only dierence that curly braces dont allow for substitution, try
puts stdout {He said \"$x\"}
and
puts stdout "He said \"$x\""
where the backslash substitution in the last code snippet works in the tclsh but not as an .Tcl argument, use
puts stdout "He said \$x\\"
instead. Hence, using braces allows you to induce a substitution at a later time
set y {He said \"$x\"} puts stdout [subst $y]
Procedures
Tcl procedures are the equivalent of R functions. The proc command is used to dene procedures
proc procname arglist body
Note that, as opposed in R, procedure names do not conict with variable names.
proc bmi {height weight} { set bmi [expr $weight/pow($height,2)] return $bmi }
As R functions do, Tcl procedures return their last expression evaluated. The curly braces dont perform any dierent in the procedure syntax: they group arguments (space) or commands (new lines) and delay the substitution until the procedure is called.
Strings
Within Tcl, the basic philosophy is that everything is a string. [...]. Other data structures (such as proc, dict, list, handle) are built on top of this fundamental assumption. [see wiki.tcl.tk] The Tcl string command provides a collection of string operations. Its rst argument determines the operation to perform [tcl.tk man] A few examples are:
string length {Hello World!} set col [string range {green world} 0 4] string equal green $col set x 5.4 string is integer $x
Lists
Lists are like vectors in R one dimensional arrays. Lists are created with the list command
set names [list Jeff Bob Lea Tiffany]
Here some basic list manipulations, read the online manual on lists, join and split for more information.
lindex $names 2 lrange $names [list 1 3] lset names 1 Bobby llength $names lappend names Paul ;# access third element ;# access 2nd to 4th element ;# replace element ;# length of the list ;# append one element ;# combine two lists ;# search for ff
concat $names [list Emilio Berta] lsearch -all -inline $names *ff*
where the asterisk (*) in the last example stands for any string.
Arrays
A Tcl array is similar to the list data structure in R. Indices of arrays are keys (strings). See the tcl manual and wiki entry. The basic syntax is
set array("key") "your string" set $array("key") ;# define an array element ;# access an element
To avoid possible errors, do not use space characters in the key, as parentheses do not group. Arrays are one dimensional, but nothing stops you from using 1,1 and 1,2 etc. as the key string.
is the same as
if{$str1 eq $str2} { ... }
Note: You can control loop execution with the break and continue commands. The break command causes immediate exit from a loop, while the continue command causes the loop to continue with the next iteration. [Brent Welch]
;# num = num + 1
Events
A single event loop permeates everything in Tcl/Tk programs that deal with I/O. When things happen on les, sockets, the GUI, timers or other input sources, events re and Tcl callbacks are invoked, simple as that. [tcl.tk] Callbacks can be triggered by button clicks in GUIs, keyboard input or after a certain time delay, to name a few. Graphical user interfaces (GUIs) work with event binding. We will discuss them in the appropriate Tk section. The after command is used to delay the execution of a command to sometime in the future. The vwait command enters the event loop until a predened variable gets modied. Idle events are processed when Tcl has nothing to do. They are registered with the after idle command.
A more native feel to invoke Tcl procedures in R gives the tcl function. For example
> bar <- "x" > tcl("set", bar, 1:5)
assigns the Tcl variable x the list (vector) 1 2 3 4 5. Note how R converts its data structure here a vector to a Tcl list.
Tcl variables in R
You can of course access every Tcl variable in R via the .Tcl or tcl function. It is, however, possible to create an R variable which links to a Tcl variable
> x <- tclVar("3")
RTcl1,
This creates the R variable x which links to a global Tcl variable called where the number gets for every new R/Tcl variable incremented
> .Tcl(set Rtcl1)
or change it with
> tclvalue(x) <- "3.26456"
Remember, every Tcl variable holds a string as its base type! Hence if you need to use a Tcl variable holding a integer within an R routine, use
> as.numeric(tclvalue(x))
Callbacks
Whenever you want to invoke an R function from Tcl, you need to get the hex-address of the R function. Say your function of interest is
foo <- function(a,b) { cat(paste("you entered: a=",a," and b=",b,\n, sep=)) }
You can get the Tcl command to invoke the function as follows
> .Tcl.callback(foo) [1] "R_call 0x22b88a0 %a %b"
So
> .Tcl(R_call 0x22b88a0 3 4) you entered: a=3 and b=4 <Tcl>
You can load Tcl packages either with the tclRequire function form within R or with the Tcl command
% package require Img
if you were to load the Img package. Emacs allows you to execute Tcl code interactively line by line. Another good tool which supports command completions with the TAB key is a program (tk extension) called tkcon.