LTK - A Lisp Binding To The TK Toolkit: Peter Herth February 5, 2006
LTK - A Lisp Binding To The TK Toolkit: Peter Herth February 5, 2006
LTK - A Lisp Binding To The TK Toolkit: Peter Herth February 5, 2006
Peter Herth
February 5, 2006
Contents
1 Introduction 3
2 Installation 4
3 Tutorial 5
3.1 First steps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2 A more complex example . . . . . . . . . . . . . . . . . . . . . 6
3.3 Canvas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3.1 Managing graphical objects . . . . . . . . . . . . . . . 9
3.3.2 Example . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.4 Radio-button . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.5 Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.6 Screen functions . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.7 Window manager functions . . . . . . . . . . . . . . . . . . . 14
3.8 Parameters for with-ltk . . . . . . . . . . . . . . . . . . . . . . 15
3.9 Running it manually . . . . . . . . . . . . . . . . . . . . . . . 15
3.10 Special variables . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.11 Generic functions . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.12 The pack geometry manager . . . . . . . . . . . . . . . . . . . 16
3.13 The grid geometry manager . . . . . . . . . . . . . . . . . . . 17
3.14 Configuring widgets . . . . . . . . . . . . . . . . . . . . . . . . 17
4 Event handling 18
4.1 command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.2 bind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1
5 Widgets 21
5.1 Button . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.2 Canvas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.3 Check-button . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.4 Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.5 Frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
5.6 Label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.7 Labelframe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.8 Listbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.9 Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.10 Menubutton . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.11 Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.12 Paned-window . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.13 Radio-button . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.14 Scale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.15 Scrollbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.16 Spinbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.17 Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
5.18 Toplevel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.19 Widget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7 ltk-remote 58
8 ltk-mw 58
8.1 progress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
8.2 history-entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
8.3 menu-entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2
1 Introduction
Tk is a graphics toolkit for the tcl programming language developed by John
Ousterhout. Initially developed for the X-Window system, it has been ported
to a wide selection of operating systems, including Windows and MacOs. Due
to ist ubiquous nature, its an ideal candidate to write a portable GUI library
for Lisp.
While one can find many code snippets how to set up a communication
with Tk from Lisp, the use of those to create actual programs, requires tcl/tk
knowledge. In fact this way the GUIs are created by tcl code put into lisp
programs. But one does not become a Lisp programmer to then write the
GUIs in tcl/tk. So the Ltk library was born, to create a wrapper around Tk
in pure Lisp. Ideally, no tcl/tk knowledge is required to write GUIs. However
the lisp code is made closely to the tcl/tk library structure, so that the man
pages for the tk widgets can serve as a detailled reference. They should be
readable without any tcl knowledge.
The main objective for Ltk was to create a GUI library which is portable
across different operating systems and Common Lisp implementations. Fur-
thermore it should be easy to set up. So with the exception of one single
function, the whole code of ltk is pure ANSI Common Lisp. No external
programs besides a standard installation of tcl/tk are required.
Ltk supports the following Lisp systems: Allegro, CMUCL, CLisp, ECL,
LispWorks, OpenMCL, SBCL. Ltk was successfully tested using Lispworks,
CLisp, CMUCL, SBCL under Linux and Lispworks, CLisp, and SBCL using
Mac OS X, CLisp, Allegro and Lispworks using Windows.
3
2 Installation
This is the shortest section of this document. You just compile the file:
(compile-file "ltk")
(load "ltk")
Now ltk is ready to use. For trying out the examples of this document, you
might want to change into the Ltk package:
(in-package :ltk)
(ltktest)
(ltk::ltk-eyes)
To use Ltk you need of course tcl/tk installed. This should be default on
most Linux systems, for Windows/Mac OS you need to download and install
tcl/tk. Ltk has been tested against Tcl/Tk 8.4, but other versions should
work also.
Alternatively, you can use ASDF to load ltk. If you have a symbolic link
to ltk.asd in your site-systems directory a simple (require ’ltk) compiles and
loads ltk (assuming you have ASDF loaded). And it is even installable via
ASDF-INSTALL!
4
3 Tutorial
3.1 First steps
Let’s start with the obligatory “hello world” type of program:
(defun hello-1()
(with-ltk ()
(let ((b (make-instance ’button
:master nil
:text "Press Me"
:command (lambda ()
(format t "Hello World!~&")))))
(pack b))))
5
NEVER use pack and grid for the same container, unpredictable behaviour
may the result (or rather, the program will very predictably crash).
The example hello-2 shows how you group 2 buttons within a frame and
configure widgets in general. The created frame is given as the master pa-
rameter to the button creations. This automatically ensures that the buttons
are packed within the frame. To change the appeareance of the Frame f, the
configure function is used. This is a very generic function, which can be
used upon any tk object. It takes two arguments, the name of the configu-
ration option and the value to set into it. The value can be any tk object or
any properly printable Lisp object.
6
In this case, we set the width of the border of the frame to 3 and make it
a sunken border. Other styles would be raised, ridge, groove, flat and solid.
For a comprehensive list of configuration options look in the manpage of the
tk widgets as well as man options for options shared by all tk widgets.
3.3 Canvas
The canvas widget is used to display all kind of graphics output. Graphic
components are defined as objects like line, circle and photoimage which are
displayed on the canvas. These objects can be modified through methods to
change their appearance. The display and redrawing is handled by the canvas
widget automatically, so that the user does not need to care for that. For
convenience, ltk adds a scrolled-canvas widget which contains a canvas widget
and adds automatically scrollbars to it. You gain access to the contained
canvas with the canvas method.
A canvas widget is created by the make-canvas function. It has the
optional arguments width and height for the width and height used to
display the canvas widget. The drawing region itself can be bigger, its size is
set by the scrollregion method, which has the canvas and the dimension
as the coordinates x0 y0 and x1 y1 as parameters.
Objects to be displayed in a canvas are created via the create-xxx meth-
ods, with xxx the type of object to be created. They take the canvas as
first argument and return an index (integer) which is used as handle for the
modifying functions. A list of currently supported objects and the create
method parameters:
pieslice (default) Draw the ark as the slice of a pie, that is an arc
with 2 lines to the center of the circle.
chord Draw the arc as an arc and a line connecting the end points of
the arc.
arc Draw only the arc.
7
(create-bitmap canvas x y &key bitmap)
Creates an bitmap on the canvas, if bitmap is given, its displayed in
this item. Special configuration options are:
anchor anchorPos
bitmap bitmap
foreground color
background color
anchor anchorPos
image image
activeimage image
disabledimage image
arrow where one of none (no arrow), first (arrow on first point of line),
last and both.
arrowshape shape
capstyle style butt, projecting, or round.
joinstyle style bevel, miter, or round.
smooth method 0 or bezier
splinesteps number Degree of smoothness if smooth is specified.
8
(create-oval canvas x0 y0 x1 y1)
Creates an oval fitting within the rectangular of the given coordinates.
(create-polygon canvas coords)
Similiar to create-line, creates a closed polygon.
Special configuration options for polygon items (see itemconfigure) are:
joinstyle style bevel, miter, or round.
smooth method 0 or bezier
splinesteps number Degree of smoothness if smooth is specified.
(create-rectangle canvas x0 y0 x1 y1)
Creates an rectangle with the given coordinates.
(create-text canvas x y text)
Creates a text displaying object at the position x,y. Text is the string
to be displayed. Special configuration options are:
anchor anchorpos
font fontname
justify justification left,right, or center.
text string
width length Line length for wrapping the text, if 0, no wrapping
happens.
9
(scrollregion canvas x0 y0 x1 y1)
Set the scroll region of the canvas. x0 y0 are the coordinates of the
upper left, x1 y1 of the lower right corner of the scroll region.
dash pattern
activedash pattern
disableddash pattern
dashoffset offset
fill color name of a color to fill the item, or empty string for none.
activefill color
disabledfill color
outline color
activeoutline color
disabledoutline color
offset offset
outlinestipple bitmap
activeoutlinestipple bitmap
stipple bitmap
activestipple bitmap
disabledstipple bitmap
state state One of normal, disabled or hidden.
tags taglist
width outlinewidth
activewidth outlinewidth
disabledwidth outlinewidth
10
3.3.2 Example
The function canvastest demonstrates the basic canvas usage:
(defun canvastest()
(with-ltk ()
(let* ((sc (make-instance ’scrolled-canvas))
(c (canvas sc))
(line (create-line c (list 100 100 400 50 700 150)))
(polygon (create-polygon c (list 50 150 250 160 250
300 50 330 )))
(text (create-text c 260 250 "Canvas test")))
(pack sc :expand 1 :fill :both)
(scrollregion c 0 0 800 800)
)))
11
3.4 Radio-button
3.5 Text
The text widget is a very powerful text editor. It allows displaying and editing
of texts of arbitrary size. It supports fancy text display by attaching tags
to sections of the displayed text. The tags can be customized by specifying
font and color of text associated with the tag and even bind events to the
corresponding text.
Methods:
(clear-text text)
Clear the content of the widget.
(text text)
Get the content of the widget.
12
(load-text text filename)
Loads the content of the widget from the file named by filename. Note:
filename is a string to be interpreted by tcl/tk on the client computer.
(window-width (tl))
Give the width of the widget in pixels. This function can be called on
widgets as well as toplevel windows.
13
(window-height (tl))
Give the height of the widget in pixels. This function can be called on
widgets as well as toplevel windows.
(window-x (tl))
Give the x position of the widget in pixels.
(window-y (tl))
Give the y position of the widget in pixels.
(withdraw toplevel)
Withdraw the window from display.
(normalize toplevel)
Set the state of the window to normal display.
(iconify toplevel)
Iconify the window.
(deiconify toplevel)
De-iconify the window.
(geometry toplevel)
Read the geometry string for the window.
14
(set-geometry toplevel width height x y)
Set the geometry for the window.
(on-close toplevel fun)
Set fun to be called whenever the close button of the window is pressed.
(on-focus toplevel fun)
Call fun whenever the window gets the focus.
Table 1: Possible values and their description for the :debug keyarg. The
value can be given in the form of the number or the keyword.
In the examples so far the parameter list for the macro with-ltk was
kept empty. Using it, the behaviour of with-ltk can be fine tuned. At the
moment the only used keyword is :debug. Valid values for it are listed in
table 1.
15
3.10 Special variables
The following special variables are defined:
(value widget) Reads/sets the value of the widget. Applicable for: check-button,
radio-button, menucheckbutton, menuradiobutton, scale.
(text widget) Reads/sets the text of the widget. Depending on the wid-
get, this can be text displayed on the widget (button) or contained as
data (entry). Applicable for button, check-button, entry, label,
labelframe, spinbox, text.
:side The direction in which the widgets are packed. Possible values are
:left , :right, :top (default), :bottom.
:expand If t, then the packed widget may take more place than
:fill Allows the packed widget to grow in the given direction, if it gets
expanded. Possible values are :none (default), :x, :y or :both needed.
16
:after widget Pack it after the widget.
:anchor direction Specify which point of the widget to use for anchoring it,
for example :ne for the upper right corner.
17
borderwidth width borderwidth in pixels
cursor cursorname Set the icon for the mouse cursor. A list of portable
names is in the variable *cursors.
relief value Effect for border display. May be raised, sunken, flat, ridge,
solid, or groove.
orient orientation The orientation of the widget (e.g. for scrollbars). May
be horizontal or vertical.
underline index The index of the character to underline in the text of the
widget for keyboard traversal.
4 Event handling
There are two ways to get notified by Tk events: command and bind. Widgets,
which have a default event type, like pressing buttons, define a command
initarg. With it, a function can be bound to this default event type. This is
a function, that will be called with zero or one parameter, depending on the
widget type. For those that use it, this parameter will be the value of the
widget (example value of the scale widget).
18
widget argument description
button - called when the button is clicked
check-button value report the value when the button is clicked
listbox selection a list of the selected indices (0 for first) whenever
the listbox is clicked
scale value whenever the value is changed, called with the new
value
spinbox value whenever the value of the spinbox is changed by
the buttons, the new one is returned
4.1 command
With the command property a function for handling the default event type of
widgets can be specified. This can be done with the :command initarg or the
command accessor (settable) for those widgets. The widgets that support the
command property are listed in table 2. The first column lists the widgets,
the second which arguments the function is passed (if any) and the third
one gives a brief description about when the event happens and what the
arguments contain.
4.2 bind
A more generic and complex event type can be created via the bind function.
With it for any widget type events can be defined, the function bound to it
always needs to accept one parameter an event structure. Its usage is: (bind
widget event function)1
A scribble example:
(defun scribble ()
(with-ltk ()
(let* ((canvas (make-instance ’canvas))
(down nil))
(pack canvas)
1
Currently the event has to be specified as a string as with Tk. In future releases
perhaps a more Lispy style might be used.
19
(bind canvas "<ButtonPress-1>"
(lambda (evt)
(setf down t)
(create-oval canvas
(- (event-x evt) 10) (- (event-y evt) 10)
(+ (event-x evt) 10) (+ (event-y evt) 10))))
(bind canvas "<ButtonRelease-1>" (lambda (evt)
(declare (ignore evt))
(setf down nil)))
(bind canvas "<Motion>"
(lambda (evt)
(when down
(create-oval canvas
(- (event-x evt) 10) (- (event-y evt) 10)
(+ (event-x evt) 10) (+ (event-y evt) 10))))))))
20
5 Widgets
In this section the available widgets are listed and described.
21
5.1 Button
The following keyword arguments are available for creating an instance of
the button and for configuring it
anchor specify the alignment of text/image drawn on the widget, one of (:n
:w :s :e :nw :sw :se :ne) with :nw designating the top left corner
bitmap the bitmap to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
compound
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
default
disabledforeground
highlightbackground
highlightcolor
highlightthickness
22
image the image to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
overrelief relief of the border, when the mouse is over the widget
repeatdelay
repeatinterval
state
text
underline
wraplength
23
5.2 Canvas
The following keyword arguments are available for creating an instance of
the canvas and for configuring it
confine if t (default) allowed values for view are confined to the scrollregion
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
highlightbackground
highlightcolor
highlightthickness
insertbackground
insertborderwidth
insertofftime
insertontime
insertwidth
offset
selectbackground
selectborderwidth
24
selectforeground
state
xscrollcommand
xscrollincrement
yscrollcommand
yscrollincrement
25
5.3 Check-button
The following keyword arguments are available for creating an instance of
the check-button and for configuring it
anchor specify the alignment of text/image drawn on the widget, one of (:n
:w :s :e :nw :sw :se :ne) with :nw designating the top left corner
bitmap the bitmap to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
compound
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
disabledforeground
highlightbackground
highlightcolor
highlightthickness
image the image to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
26
indicatoron
offrelief
offvalue
onvalue
overrelief relief of the border, when the mouse is over the widget
selectcolor
selectimage
state
text
underline
wraplength
27
5.4 Entry
The following keyword arguments are available for creating an instance of
the entry and for configuring it
background background color of the widget
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
disabledbackground
disabledforeground
exportselection
highlightbackground
highlightcolor
highlightthickness
insertbackground
insertborderwidth
insertofftime
insertontime
insertwidth
invalidcommand
readonlybackground
28
selectbackground
selectborderwidth
selectforeground
show
state
text
validate
validatecommand
xscrollcommand
29
5.5 Frame
The following keyword arguments are available for creating an instance of
the frame and for configuring it
class the class of the widget, used for lookup in the option database. This
option cannot be changed after the widget creation.
container if t, then the widget will be used as a container for other widgets.
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
highlightbackground
highlightcolor
highlightthickness
visual
30
5.6 Label
The following keyword arguments are available for creating an instance of
the label and for configuring it
anchor specify the alignment of text/image drawn on the widget, one of (:n
:w :s :e :nw :sw :se :ne) with :nw designating the top left corner
bitmap the bitmap to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
compound
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
disabledforeground
highlightbackground
highlightcolor
highlightthickness
image the image to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
31
padx padding around text displayed on the widget
state
text
underline
wraplength
32
5.7 Labelframe
The following keyword arguments are available for creating an instance of
the labelframe and for configuring it
class the class of the widget, used for lookup in the option database. This
option cannot be changed after the widget creation.
container if t, then the widget will be used as a container for other widgets.
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
highlightbackground
highlightcolor
highlightthickness
labelanchor
labelwidget
text
33
visual
34
5.8 Listbox
The following keyword arguments are available for creating an instance of
the listbox and for configuring it
activestyle the style for drawing the active part (dotbox, none, underline
(default))
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
disabledforeground
exportselection
highlightbackground
highlightcolor
highlightthickness
listvariable
selectbackground
selectborderwidth
selectforeground
selectmode
setgrid
35
state
xscrollcommand
yscrollcommand
36
5.9 Menu
The following keyword arguments are available for creating an instance of
the menu and for configuring it
activeborderwidth the border width for active widgets (when the mouse
cursor is over the widget)
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
disabledforeground
postcommand
selectcolor
tearoffcommand
title
type
37
5.10 Menubutton
The following keyword arguments are available for creating an instance of
the menubutton and for configuring it
anchor specify the alignment of text/image drawn on the widget, one of (:n
:w :s :e :nw :sw :se :ne) with :nw designating the top left corner
bitmap the bitmap to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
compound
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
direction
disabledforeground
highlightbackground
highlightcolor
highlightthickness
image the image to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
38
indicatoron
menu
state
text
underline
wraplength
39
5.11 Message
The following keyword arguments are available for creating an instance of
the message and for configuring it
anchor specify the alignment of text/image drawn on the widget, one of (:n
:w :s :e :nw :sw :se :ne) with :nw designating the top left corner
aspect Aspect ratio for the wrapping of the text. 100 means that the text
is redered as wide as, tall, 200 twice as wide.
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
highlightbackground
highlightcolor
highlightthickness
text
40
5.12 Paned-window
The following keyword arguments are available for creating an instance of
the paned-window and for configuring it
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
handlepad
handlesize
opaqueresize
sashcursor
sashpad
sashrelief
sashwidth
showhandle
41
5.13 Radio-button
The following keyword arguments are available for creating an instance of
the radio-button and for configuring it
anchor specify the alignment of text/image drawn on the widget, one of (:n
:w :s :e :nw :sw :se :ne) with :nw designating the top left corner
bitmap the bitmap to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
compound
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
disabledforeground
highlightbackground
highlightcolor
highlightthickness
image the image to display on the widget, the display is affected by the
options ’anchor’ and ’justify’
42
indicatoron
offrelief
overrelief relief of the border, when the mouse is over the widget
selectcolor
selectimage
state
text
underline
nil value for the radio button group to take, when the button is selected
nil name of the radio button group the button shall belong to as a string
wraplength
43
5.14 Scale
The following keyword arguments are available for creating an instance of
the scale and for configuring it
activebackground background of the active area
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
from
highlightbackground
highlightcolor
highlightthickness
length
repeatdelay
repeatinterval
resolution
44
showvalue
sliderlength
sliderrelief
state
tickinterval
to
troughcolor
45
5.15 Scrollbar
The following keyword arguments are available for creating an instance of
the scrollbar and for configuring it
activerelief the border relief for active widgets (when the mouse cursor
is over the widget)
command
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
elementborderwidth
highlightbackground
highlightcolor
highlightthickness
jump
repeatdelay
repeatinterval
troughcolor
46
5.16 Spinbox
The following keyword arguments are available for creating an instance of
the spinbox and for configuring it
activebackground background of the active area
button.background
button.cursor
button.relief
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
disabledbackground
disabledforeground
exportselection
format
from
highlightbackground
highlightcolor
highlightthickness
insertbackground
insertborderwidth
47
insertofftime
insertontime
insertwidth
invalidcommand
justify justification of the text on the widget
readonlybackground
relief relief of the widgets border (raised, sunken, ridge, groove)
repeatdelay
repeatinterval
selectbackground
selectborderwidth
selectforeground
command (AND COMMAND (PROGN (ADD-CALLBACK (NAME WID-
GET) COMMAND) (NAME WIDGET)))
state
takefocus if true, the widget can take the focus
text
to
validate
validatecommand
values
width width of the widget
wrap
xscrollcommand
48
5.17 Text
The following keyword arguments are available for creating an instance of
the text and for configuring it
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
exportselection
highlightbackground
highlightcolor
highlightthickness
insertbackground
insertborderwidth
insertofftime
insertontime
insertwidth
maxundo
49
relief relief of the widgets border (raised, sunken, ridge, groove)
selectbackground
selectborderwidth
selectforeground
setgrid
spacing1
spacing2
spacing3
state
tabs
undo
wrap
xscrollcommand
yscrollcommand
50
5.18 Toplevel
The following keyword arguments are available for creating an instance of
the toplevel and for configuring it
background background color of the widget
class the class of the widget, used for lookup in the option database. This
option cannot be changed after the widget creation.
container if t, then the widget will be used as a container for other widgets.
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
highlightbackground
highlightcolor
highlightthickness
menu
use
visual
51
5.19 Widget
The following keyword arguments are available for creating an instance of
the widget and for configuring it
cursor mouse pointer to display on the widget (valid values are listed in
*cursors*)
52
6 Under the hood
In this section, the technical detaills of the implementation and workings of
ltk are explained. Reading this section should not be neccessary to use ltk,
but helps understanding it and serves as a documentation for those, who
want to extend ltk.
The Tk library is a GUI library for the tcl programming language. It
is used via the program wish. Commonly, it is used as the shell to execute
tcl/tk programs. But when no script name to execute is being given, it starts
in an interactive mode, using stdin to read commands and stdout to print
the results. This can be used to enter the tcl commands manually in an
interactive session or, as used by ltk to access wish from another program.
Every Lisp I know of, offers a function to run a program in a subprocess and
to communicate to its stdin/stdout streams. The ltk function do-execute
wraps these platform-dependant functions in a generic one. Its parameter is
the name of the program to start as a string, a list with the parameters for
the program. It starts the program as a subprocess of the Lisp process and
returns a two-way stream to communicate with the program. To send some
text to the program, its just written into the stream, and likewise output
from the program can be read from the string.
All ltk widget creation functions actually create two objects: the CLOS
object to represent the widged on the Lisp side, and the corresponding Tk
object.
The root class of the ltk class hierarchy is the tkobject class. It has only
one slot: the name of the object. In tcl objects are tracked by their names,
very similiarly like symbols in Lisp. To represent all widgets the widget class
is derived from tkobject. It adds the slots for the object being the master
of the widget and the path string for the widget. As mentioned before, all
tcl objects are referenced by their name, and all tk widgets have to be put in
an hierarchy. This is represented by a path-like naming system. The name
of the root object is just “.”. Creating a frame named frame1 below it would
lead to a path name .frame1. A button called button1 placed into this
frame gets the pathname .frame1.button1. Both the naming and the path
creation is automatically handled by ltk. To create both only the reference
to the master is needed. In an after-method to the initialize-instance
method of widget, the name is created as an unique string and the pathname
is created by appending this name to the pathname of the master widget, or
“.”, if the widget has no master specified. The unique name is created by
53
appending an upcounting number to the letter “w”. Finally the method calls
the create methode upon the new widget. This create method is, where the
code interfacing with tk takes place. So to support new tk widgets, only a
subclass of widget has to be made and a create method to be written.
Internally used special variables are:
*counter* The counter variable used to give widgets unique names (wn,
where n is the counter variable, that gets incremented upon use).
*event-queue* If event messages are read while waiting for a data message
they are buffered in that list.
6.1 Communication
At the startup of the wish process, some tcl helper functions are defined and
then the functions in the list *INIT-WISH-HOOK*. These purpose of these
functions is to perform initialisations, e.g. loading Tk extensions.
All communication from Tk to Lisp takes place in form of lists, which are
read-able. The first element of the list is a keyword, which determines what
kind of information is following. :data is the answer to a call to a function
like reading out the content of a widget. :callback is sent upon a callback
event and :event for an event created by the bind function. This design
is neccessary, because events can be generated (and thus messages to Lisp
sent), while Lisp is waiting for a data answer. So the function read-data
can buffer those events until the requested data arrives. Only after the data
request has been fufilled, all pending events are processed.
54
6.2 Writing Ltk extensions
It is difficult to give a fully generic set of instructions how to write Ltk
extensions, as some part of it depends on the package that is to be wrapped,
but at the example of the tix extension set, a very common case can be shown.
For sake of brevity, here only the creation of a partial implementation of the
tixBalloon widget is demonstrated.
The first step is to create a Lisp package to host the extension library:
(defpackage "LTK-TIX"
(:use "COMMON-LISP"
"LTK")
(:export
"BALLOON"
"BALLOON-BIND"))
(in-package ltk-tix)
(eval-when (:load-toplevel)
(setf *init-wish-hook* (append *init-wish-hook*
(list (lambda ()
(send-wish "package require Tix"))
))))
Now we need to create the Lisp class that wraps the balloon widget. First
we need a class definition:
Unless there are some special storage needs, an empty sub-class of widget
is all one needs. What is still missing, is the Tk code to actually create the
55
widget. It is put in the initialize-instance after-method for the widget
class. This is easy to do when we look how the widget is created on the Tk
side:
tixBalloon pathname
where pathname is the path string describing the widget to be created.
This translates into Lisp code as:
path is an accessor function created for the widget class. The correspond-
ing slot is automatically filled in the initialize-instance method for the
widget class. Now we can create instances of the balloon widget, what is left
to do is to define the methods upon it.
We want to implement the bind command upon the balloon widget. First
lets again look at the Tk side of it:
pathname bind widget options
pathname is the path of the balloon widget, widget is another widget
for which the balloon help should be displayed and options are additional
command options. The following options should be implemented:
-msg text Sets the displayed message to text.
We call this balloon-bind to avoid name conflicts with the function bind
defined by the Ltk package. It is a generic function of two parameters, the
balloon widget and the widget the message should be bound to. The message
is to be specified by the keyword parameters. The actual implementation of
the generic function is very straight forward and looks like this:
2
It is not required to have a defgeneric definition for each generic function, as to the
standard, defmethod implicitly generates the definition if they do not exist, but as SBCL
issues a warning in this case and shipped code preferrably should not issue warnings on
compilation, I add the defgeneric statements for all generic functions I create.
56
(defmethod balloon-bind ((balloon balloon) (widget widget)
&key msg balloonmsg statusmsg)
(format-wish "~a bind ~a~@[ -msg {~a}~]~
~@[ -balloonmsg {~a}~]~
~@[ -statusmsg {~a}~]"
(path balloon) (path widget) msg balloonmsg statusmsg))
Format wish is a wrapper around the format function, that sends the output
to wish and automaticalls flushes the output buffer, so that the statement is
directly executed by wish. It is worth noting, that the Lisp format function
has some very nice options, allowing us to elegantly implement the optional
keyword arguments. The ~@[ ~] format directive peeks at the next argument
in the list and only when it is non-nil, the format code inside is executed,
otherwise, this argument will be consumed. As unspecified keyword argu-
mends are set to nil, if no argument is specified this nicely fits to this format
directive. So ~@[ -msg {~a}~] will output nothing, if the argument msg is
not given at the invokation of balloon-bind, or print “ -msg xxx”, where
xxx is the content specified for the msg argument.
57
7 ltk-remote
As the connection between Lisp and tcl/tk is done via a stream, it is obvious
that this connection can easily be run over a tcp socket. This allows the gui to
be displayed on computers different to the one running the Lisp program. So
ltk applications are not only network transparent accross different operating
systems, they are actually very efficiently network transparent, since the
creation of a button requires only in the magnitude of 100 bytes of network
transfer. Likewise, only the generated events are transmitted back to the
Lisp server.
The only difference for the lisp application to enable remote access is
using the with-remote-ltk port macro instead of the with-ltk macro. As
sockets are not part of the ANSI Common Lisp standard, currently only
CMUCL, SBCL and Lispworks are supported by ltk-remote.
The only thing required on the client computer is tcl/tk installed and the
remote.tcl script (which has less than 30 lines of code in it). Connection to
the lisp process is established by
Where hostname is the name of the computer running the lisp process and
port the port on which the lisp process is listening.
8 ltk-mw
Ltk-mw is a “megawidgets” package inspired by PMW (Python Mega Wid-
gets). It contains extension widgets for Ltk written in Lisp. Besides serving
as an example, how to extend Ltk, it provides usefull new widgets listed
below.
8.1 progress
A progress-bar widget. It displays a bar which covers the width of the widget
in the given percentage. The widget has two settable accessor functions:
percent and bar-color.
58
8.2 history-entry
History-entry is an entry widget, that provides a history of all input. The
history can be browsed with the cursor-up and down keys. If the :command
initarg is passed to make-instance when creating an instance of the widget,
the specified function is called whenever the user pressed the return key.
The function gets passed the text in the widget and the input field of the
widget is cleared.
8.3 menu-entry
A combo-box style entry widget, that displays a menu of input content, when
the user clicks the widget. The initial content for the menu is passed as a
list to the :content initarg. To modify the menu, the generic functions
(append-item entry string) and (delete-item entry index) can be used.
59
9 Example: A “Hello World” application
This section contains a step-by-step example how to create a “stand-allone”
application using Ltk and SBCL. Fist of all, you need the application itself:
(defpackage :hello-world
(:use :common-lisp :ltk)
(:export #:main))
(in-package :hello-world)
(defun main ()
(setf *debug-tk* nil)
(with-ltk ()
(let ((b (make-instance
’button
:text "Hello World!"
:command (lambda ()
(do-msg "Bye!" "Hello World!")
(setf *exit-mainloop* t)))))
(pack b))))
This may not be the worlds greatest application, but I shows the impor-
tant steps. First rule is: whenever you write lisp code, put it in a package.
While this seems overkill, it is the easiest solution to avoid symbol conflicts,
and if your code grows you will need a package anyway.
Next, you want to build your application, here is a shell-script that will
do that work:
This script compiles and loads both ltk and hello-world. Then it calls
save-lisp-and-die to create the core file for the application. Put it in a file
called build-hello, make it executable and run it to build the application.
60
Once you have build your core, all what is left is running the application.
For that, a small startup script will create the “executable” feeling:
If you put it in a file called helloworld, and make it executable, you can
start your application just by typing helloworld at the shell prompt.
To deliver your application, you need to provide three files: sbcl, hello-world.core
and helloworld. sbcl is the sbcl launching program, you can find its lo-
cation by typing which sbcl. It is less than 300k in size, so just copy and
deliver it with your custom core and startup scipt.
Thats all :).
61
Index
canvastest, 47 colormap, 21, 24, 42
command, 13, 35, 38
activebackground, 13, 17, 22, command-scrollbar, 37
28, 29, 33, 35, 37, 38 compound, 13, 17, 22, 29, 33
activeborderwidth, 28 configure, 9
activeforeground, 13, 17, 22, confine, 15
28, 29, 33 container, 21, 24, 42
activerelief, 37 create-arc, 44
activestyle, 26 create-bitmap, 44
anchor, 9, 13, 17, 22, 29, 31, create-image, 45
33 create-line, 45
append-text, 48 create-line*, 45
aspect, 31 create-oval, 45
autoseparators, 40 create-polygon, 45
background, 9, 13, 15, 17, 19, create-rectangle, 46
21, 22, 24, 26, 28, 29, create-text, 46
31--33, 35, 37, 38, 40, create-window, 46
42, 43 cursor, 10, 13, 15, 17, 19, 21,
bigincrement, 35 22, 24, 26, 28, 29, 31--33,
bitmap, 9, 13, 17, 22, 29, 33 35, 37, 38, 40, 42, 43
borderwidth, 10, 13, 15, 17, 19, default, 13
21, 22, 24, 26, 28, 29, deiconify, 51
31--33, 35, 37, 38, 40, digits, 35
42, 43 direction, 29
button, 13 disabledbackground, 19, 38
button.background, 38 disabledforeground, 13, 17, 19,
button.cursor, 38 22, 26, 28, 29, 33, 38
button.relief, 38
elementborderwidth, 37
canvas, 15, 44 entry, 19
cbcommand, 17 exportselection, 19, 26, 38, 40
check-button, 17
class, 21, 24, 42 font, 13, 17, 19, 22, 24, 26,
clear-text, 49 28, 29, 31, 33, 35, 38,
closeenough, 15 40
62
foreground, 10, 13, 17, 19, 22, installation, 4
24, 26, 28, 29, 31, 33, invalidcommand, 19, 39
35, 38, 40 itemconfigure, 47
format, 38
frame, 21 jump, 37
from, 35, 38 justify, 10, 14, 18, 19, 22, 30,
31, 34, 39
geometry, 51
grid, 9 label, 22, 35
labelanchor, 24
handlepad, 32 labelframe, 24
handlesize, 32 labelwidget, 24
height, 13, 15, 17, 21, 22, 24, length, 35
26, 29, 32, 33, 40, 42 listbox, 26
hello-1, 5 listvariable, 26
hello-2, 6 load-text, 49
highlightbackground, 13, 15, 17, Ltk extensions, 54
19, 21, 22, 24, 26, 29, ltk-mw, 57
31, 33, 35, 37, 38, 40, ltk-remote, 57
42
highlightcolor, 13, 15, 17, 19, maxsize, 51
21, 22, 24, 26, 29, 31, maxundo, 40
33, 35, 37, 38, 40, 42 menu, 28, 30, 42
highlightthickness, 13, 15, 17, menubutton, 29
19, 21, 22, 24, 26, 29, message, 31
31, 33, 35, 37, 38, 40, minsize, 51
42 normalize, 51
iconify, 51 offrelief, 18, 34
image, 10, 14, 17, 22, 29, 33 offset, 15
increment, 38 offvalue, 18
indicatoron, 18, 30, 33 on-close, 51
insertbackground, 15, 19, 38, on-focus, 51
40 onvalue, 18
insertborderwidth, 15, 19, 39, opaqueresize, 32
40 orient, 10, 32, 35, 37
insertofftime, 15, 19, 39, 40 overrelief, 14, 18, 34
insertontime, 15, 19, 39, 40
insertwidth, 15, 19, 39, 40 pack, 8
63
padx, 10, 14, 18, 21, 23, 24, selectforeground, 16, 20, 26,
30, 31, 34, 40, 42 39, 41
pady, 10, 14, 18, 21, 23, 24, selectimage, 18, 34
30, 31, 34, 40, 42 selectmode, 26
paned-window, 32 set-coords, 46
postcommand, 28 set-geometry, 51
setf text, 49
radio-button, 33 setgrid, 26, 41
readonlybackground, 19, 39 show, 20
relief, 10, 14, 15, 18, 19, 21, showhandle, 32
23, 24, 26, 28, 30--32, showvalue, 36
34, 35, 37, 39, 41--43 sliderlength, 36
repeatdelay, 14, 35, 37, 39 sliderrelief, 36
repeatinterval, 14, 35, 37, 39 spacing1, 41
resolution, 35 spacing2, 41
sashcursor, 32 spacing3, 41
sashpad, 32 spinbox, 38
sashrelief, 32 state, 14, 16, 18, 20, 23, 27,
sashwidth, 32 30, 34, 36, 39, 41
save-text, 49 tabs, 41
scale, 35 tag-bind, 49
screen, 42 tag-configure, 49
screen-height, 50 takefocus, 10, 14, 16, 18, 20,
screen-heigth-mm, 50 21, 23, 24, 27, 28, 30,
screen-mouse, 50 31, 34, 36, 37, 39, 41,
screen-mouse-x, 50 42
screen-mouse-y, 50 tearoff, 28
screen-width, 49 tearoffcommand, 28
screen-width-mm, 50 text, 10, 24, 40, 49
scrollbar, 37 textvariable, 14, 18, 20, 23,
scrollregion, 15, 46 30, 31, 34, 39
see, 49 tickinterval, 36
selectbackground, 15, 20, 26, title, 28
39, 41 to, 36, 39
selectborderwidth, 15, 20, 26, toplevel, 42, 49
39, 41 troughcolor, 36, 37
selectcolor, 18, 28, 34 type, 28
64
underline, 10, 14, 18, 23, 30,
34
undo, 41
use, 42
validate, 20, 39
validatecommand, 20, 39
value-radio-button, 34
values, 39
variable, 18, 36
variable-radio-button, 34
visual, 21, 25, 42
widget, 43
width, 14, 16, 18, 20, 21, 23,
25, 27, 30--32, 34, 36,
37, 39, 41, 42
window-height, 50
window-width, 50
window-x, 50
window-y, 50
withdraw, 51
wm-title, 51
wrap, 39, 41
wraplength, 14, 18, 23, 30, 34
65