- Building Applications with BLT
George A. Howlett
Cadence Design Systems, Inc. Allentown, Pennsylvania
Building Applications with BLT George A. Howlett Cadence - - PowerPoint PPT Presentation
Building Applications with BLT George A. Howlett Cadence Design Systems, Inc. Allentown, Pennsylvania What is BLT? Set of widgets and new commands. Extends the Tcl interpreter, no patching required. Features: Graph,
Cadence Design Systems, Inc. Allentown, Pennsylvania
Set of widgets and new commands.
Features:
Platforms:
Three plotting widgets available:
Many features span across all three widgets.
Run special shell with statically linked BLT commands. Dynamically load the BLT package into a vanilla wish. $ $ bltwish bltwish $ wish $ wish % package require BLT % package require BLT
Two ways to access the BLT commands.
package require BLT blt::graph .g blt::graph .g package require BLT namespace import blt::* namespace import blt::* graph .g
&DQWILQGJUDSK FRPPDQGLQWKHJOREDO QDPHVSDFH
How to plot data with the graph widget. Zooming and scrolling. Annotations. Building your own zooming graph. Customizing the graph:
Interactive graphs. Data handling. Printing. Advanced features. Managing graphs with tabsets.
Graph drawn on the canvas using Tcl code. Example in Tk widget demo. Problems:
1RFRGHIRUUHVL]LQJ
Create graph widget and add data elements with element
.
X-Y coordinates are lists of numbers. Assorted configuration options
symbol
linewidth
fill
smooth package require BLT namespace import blt::* graph .g -title ”My Graph” pack .g .g element create .g element create line1 line1 -
symbol triangle \ \
xdata {0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 … } \ \
ydata {2.61825e+01 5.04696e+01 7.28517e+01 … } Symbol types
Represents a set of data. Symbols are the data points. Usually drawn as a single trace. Each element has entry in legend. Z-ordering
Axes auto-scale
… … .g element create .g element create line2 line2 -
symbol circle -
fill red \ \
xdata {0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 … } {0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 … } \ \
ydata { {-
1.14471e+01 2.09373e+01 2.84608e+01 … } .g element create .g element create line3 line3 -
symbol square -
fill green \ \
xdata {0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 … } \ \
ydata {4.07008e+01 7.95658e+01 1.16585e+02 … }
Graph’s axis
Graph is automatically redrawn displaying the selected range.
To scroll, add or subtract same amount from both min and max. .g axis configure x .g axis configure x -
min 1.0 -
max 3.0 .g axis configure y .g axis configure y -
max 100.0 -
max 300.0
Can attach a scrollbar to any axis.
scrollbar .hs scrollbar .hs -
command {.g axis view x } -
scrollbar .vs scrollbar .vs -
command {.g axis view y } -
.g axis configure x .g axis configure x -
scrollcommand { .hs set } .g axis configure y .g axis configure y -
scrollcommand { .vs set }
Assorted options set appearance using axis
descending yes
rotate 90
title ”Y Axis”
ticklength -
5
loose yes
logscale yes
showticks no
hide yes
&KDQJHV PDGHRQ <D[LV RQO\
Labels customized by specifying callback proc.
subdivisions 5
majorticks {150 325}
stepsize 50.0
minorticks {.1 .5}
proc FormatTick { widget x } { proc FormatTick { widget x } { if { $x != 0.0 } { return if { $x != 0.0 } { return \ \$$x } $$x } return $x return $x } } .g axis configure y .g axis configure y \ \
command FormatTick
'RQWPRGLI\JUDSKZLWKLQFDOOEDFNSURF
Six types of markers:
.g marker create .g marker create text text -
text "Text Marker" -
rotate 90 \ \
coords { 0.5 300 } -
font { Helvetica 20 } .g marker create .g marker create line line -
coords { 0.7 -
Inf 0.7 Inf } \ \
dashes dash -
linewidth 2 -
image create photo myImage -file images/qv100.t.gif .g marker create .g marker create image image -
image myImage -
coords {2.0 100.0} button .g.button -text "Window Marker" -bg dodgerblue .g marker create .g marker create window window -
window .g.button -
coords {3 300}
0DUNHU SRVLWLRQV LQJUDSK FRRUGLQDWHV
Already know how to zoom in/out of a graph. Add test so we can pick corners in any direction. proc Zoom { graph x1 y1 x2 y2 } { proc Zoom { graph x1 y1 x2 y2 } { if { $x1 > $x2 } { if { $x1 > $x2 } { $graph axis configure x $graph axis configure x -
min $x2 -
max $x1 } elseif { $x1 < $x2 } { } elseif { $x1 < $x2 } { $graph axis configure x $graph axis configure x -
min $x1 -
max $x2 } } if { $y1 > $y2 } { if { $y1 > $y2 } { $graph axis configure y $graph axis configure y -
min $y2 -
max $y1 } elseif { $y1 < $y2 } { } elseif { $y1 < $y2 } { $graph axis configure y $graph axis configure y -
min $y1 -
max $y2 } } } } proc Unzoom { graph } { proc Unzoom { graph } { $graph axis configure x y $graph axis configure x y -
min {} -
max {} } }
&DQFRQILJXUHPRUHWKDQRQHD[LVDWDWLPH
Create user-selectable zoom region. Drawn with a line marker.
bind .g <ButtonPress bind .g <ButtonPress-
1> { RegionStart RegionStart %W %x %y } %W %x %y } bind .g <B1 bind .g <B1-
Motion> { RegionMotion RegionMotion %W %x %y } %W %x %y } bind .g <ButtonRelease bind .g <ButtonRelease-
1> { RegionEnd RegionEnd %W %x %y } %W %x %y } bind .g <ButtonRelease bind .g <ButtonRelease-
3> { Unzoom %W }
ButtonPress ButtonPress6HOHFWVWFRUQHU ButtonRelease ButtonRelease6HOHFWQGFRUQHU
proc RegionStart { graph x y } { proc RegionStart { graph x y } { global x0 y0 global x0 y0 $graph marker create line $graph marker create line -
coords { } -
name myLine myLine \ \
dashes dash -
xor yes set x0 $x; set y0 $y set x0 $x; set y0 $y } } proc RegionMotion { graph x y } { proc RegionMotion { graph x y } { global x0 y0 global x0 y0 $graph marker coords $graph marker coords myLine myLine \ \ “$x0 $y0 $x0 $y $x $y $x $y0 $x0 $y0” “$x0 $y0 $x0 $y $x $y $x $y0 $x0 $y0” } } proc RegionEnd { graph x y } { proc RegionEnd { graph x y } { global x0 y0 global x0 y0 $graph marker delete $graph marker delete myLine myLine Zoom $graph $x0 $y0 $x $y Zoom $graph $x0 $y0 $x $y } }
0DUNHUVZLWKRXWFRRUGLQDWHVDUHQWGUDZQ 1DPHWKHPDUNHUVRZHFDQUHIHUWRLW
[\ [\ [\ [\
Example doesn’t work. Need to translate screen
proc RegionStart { graph x y } { set x [$graph axis invtransform x $x] set x [$graph axis invtransform x $x] set y [$graph axis invtransform y $y] set y [$graph axis invtransform y $y] … } proc RegionMotion { graph x y } { set x [$graph axis invtransform x $x] set x [$graph axis invtransform x $x] set y [$graph axis invtransform y $y] set y [$graph axis invtransform y $y] … } # Screen to graph coordinates set graphX [.g axis invtranform x $screenX] set graphX [.g axis invtranform x $screenX] # Graph to screen coordinates set screenX [.g axis transform x $graphX] set screenX [.g axis transform x $graphX]
Can recursively zoom further and further in. Add feature: Stack zoom levels so user can pop back to previous zoom. set zoomStack {} set zoomStack {} proc Zoom { graph x1 y1 x2 y2 } { PushZoom $graph PushZoom $graph … … busy hold $graph ; update ; busy release $graph busy hold $graph ; update ; busy release $graph } proc Unzoom { graph } { if { ![EmptyZoom] } { eval [PopZoom] } if { ![EmptyZoom] } { eval [PopZoom] } busy hold $graph ; update ; busy release $graph busy hold $graph ; update ; busy release $graph }
8VH7FOOLVWDV]RRPVWDFN %XV\FRPPDQGSUHYHQWV DFFLGHQWDO]RRPXQ]RRP
Create zoom stack. Push/pop graph commands to restore axis ranges. proc PushZoom { graph } { proc PushZoom { graph } { global zoomStack global zoomStack set x1 [$graph axis cget x set x1 [$graph axis cget x -
min] set x1 [$graph axis cget x set x1 [$graph axis cget x -
max] set y1 [$graph axis cget y set y1 [$graph axis cget y -
min] set y2 [$graph axis cget y set y2 [$graph axis cget y -
max] set cmd ” set cmd ”$graph axis configure x $graph axis configure x -
min $x1 -
max $x2 ; $graph axis configure y $graph axis configure y -
min $y1 -
max $y2” ” lappend zoomStack $cmd lappend zoomStack $cmd } } proc PopZoom {} { proc PopZoom {} { global zoomStack global zoomStack set cmd [lindex $zoomStack end] set cmd [lindex $zoomStack end] set zoomStack [lreplace $zoomStack end end] set zoomStack [lreplace $zoomStack end end] return $cmd return $cmd } } proc EmptyZoom {} { proc EmptyZoom {} { global zoomStack global zoomStack expr {[llength $zoomStack] == 0} expr {[llength $zoomStack] == 0} } }
*HWFXUUHQWD[LVUDQJHV 6WDFNFRPPDQGVWRUHVWRUH WRFXUUHQW]RRPOHYHO 3RSODVWFRPPDQG RIIDQGUHPRYHLW
legend
position right
position left
position top
position bottom
position plotarea
hide yes
raised yes
position @450,100
grid
hide no
color lightblue
dashes 0
mapy {}
mapx {}
minor no
crosshairs
dashes dash
position @450,100
hide no
color red
.g crosshairs on .g crosshairs on .g crosshairs configure .g crosshairs configure -
color red -
dashes 2 bind .g <Motion> { bind .g <Motion> { .g crosshairs configure .g crosshairs configure -
position @%x,%y } }
Zooming graph example of interactive graph. All graph widgets/plotting packages draw graphs.
Two-way communication (back annotation) lets graph become powerful tool.
Elements have closest
Writes information into a Tcl array variable.
Options:
.g element closest 300 400 .g element closest 300 400 myInfo myInfo .g element closest 200 400 .g element closest 200 400 myInfo myInfo -
halo 1.0i .g element closest 1 40 .g element closest 1 40 myInfo myInfo -
interpolate yes .g element closest 20 10 .g element closest 20 10 myInfo myInfo line2 line1 line2 line1 puts “ puts “$ $myInfo myInfo(name) (name) is closest at is closest at $ $myInfo myInfo(index) (index)” ”
5HWXUQVLID FORVHVWHOHPHQW LVIRXQG RWKHUZLVH
You can bind
Find currently selected item using get
.g .g element element bind bind line1 line1 <Enter> { <Enter> { puts ”Touched element” puts ”Touched element” } } .g .g marker marker bind bind myLine myLine <Enter> { <Enter> { puts ”Touched marker” puts ”Touched marker” } } .g .g legend legend bind bind line1 line1 <ButtonPress <ButtonPress-
1> { puts ”selected line1” puts ”selected line1” } } set elem [.g element get current] set elem [.g element get current] set marker [.g marker get current] set marker [.g marker get current] set elem [.g legend get current] set elem [.g legend get current]
(DFKFRPSRQHQWKDVLWV RZQbind bind RSHUDWLRQ
How do you display many elements?
Let user interactively highlight elements.
Binding tag all
Can include/exclude tags with -
.g element bind .g element bind all all <Shift <Shift-
Enter> { Highlight Highlight %W [%W element get current] %W [%W element get current] } } .g element bind .g element bind all all <Shift <Shift-
Leave> { Unhighlight Unhighlight %W [%W element get current] %W [%W element get current] } } .g legend bind .g legend bind all all <ButtonPress <ButtonPress-
1> { Highlight Highlight %W [%W legend get current] %W [%W legend get current] } } .g legend bind .g legend bind all all <ButtonRelease <ButtonRelease-
1> { Unhighlight Unhighlight %W [%W legend get current] %W [%W legend get current] } } .g element configure line1 .g element configure line1 -
bindtags { myTag all all } } .g marker configure myLine .g marker configure myLine -
bindtags { myTag all all } }
Both legend and elements have activate
When active:
proc Highlight { graph elem } { proc Highlight { graph elem } { $graph $graph element element activate activate $elem $elem $graph $graph legend legend activate activate $elem $elem } } proc Unhighlight { graph elem } { proc Unhighlight { graph elem } { $graph $graph element element deactivate deactivate $elem $elem $graph $graph legend legend deactivate deactivate $elem $elem } }
Managing large sets of X-Y coordinate data as Tcl lists is slow, cumbersome.
Problems:
Tcl lists representing X and Y coordinate vectors. Internal binary format (doubles) stored in graph widget.
Often, data starts in binary format. Converted to strings, just to be converted back to doubles.
Data trapped inside of widget.
HOHPHQWV [YDOXHV \YDOXHV
'RQWWKH\DOOKDYHWKHVDPH[YDOXHV"
Recognized by graph widgets.
vector vector create create x x x x set { 0 1e set { 0 1e-
10 2e-
10 3e-
10 4e-
10 5e-
10 6e-
10 7e-
10 8e-
10 9e 9e-
10 1e-
09 1.1e-
09 1.2e-
09 1.3e-
09 1.4e-
09 1.5e-
09 … } puts [ puts [x x length] length] puts puts $x(0) $x(0) vector create vector create x x vector create vector create y y x x set {…} set {…} y y set {…} set {…} .g element configure .g element configure -
xdata x x -
ydata y y
9DULDEOHE\WKHVDPHQDPHDVYHFWRULVDOVRFUHDWHG 1HZ7FO FRPPDQG E\WKH VDPHQDPH DVYHFWRU LVFUHDWHG
Can access vector data via Tcl array variable.
end end Returns the last value. ++end ++end Automatically appends new slot to vector. Index of new slot. min min Returns the minimum value. max max Returns the maximum value.
vector create vector create x x(50) (50) set set x(0) x(0) 20.0 20.0 set set x(end) x(end) 30.0 30.0 set set x(++end) x(++end) 31.0 31.0 puts ”Range of values: puts ”Range of values: $x(min) $x(min) to to $x(max) $x(max)” ” puts ”First twenty values are puts ”First twenty values are $x(0:19) $x(0:19)” ” set set x(40:50) x(40:50) -
1
&DQVSHFLI\LQLWLDOYHFWRUVL]H $OOYDOXHVGHIDXOWWR
Tcl command associated with vector has several operations:
append Appends the lists of values or other vectors.
binread Reads binary data into vector.
delete Deletes elements by index.
dup Creates a copy of vector.
expr Computes vector expressions.
length Queries or resets number of elements.
merge Returns list of merged elements of two of more vectors.
range Returns values of vector elements between two indices.
search Returns indices of a specified value or range of values.
seq Generates a sequence of values.
sort Sorts the vector. If other vectors are listed, rearranged in same manner.
variable Maps a Tcl variable to vector. proc myProc { vector } { $vector variable $vector variable x x set x(0) 20.0 set x(end) 30.0 }
.LQGRIOLNHXSYDU5HPDSVWKHYHFWRUV YDULDEOHWRWKHORFDOYDULDEOH[
Vector’s expr
Can build data analysis routines from vector expressions.
x x expr expr { { x x + 1 } + 1 } x x expr expr { { x x + + y y } } x x expr expr { { x x * ( * (y y + 1)} + 1)} x x expr expr { sin( { sin(x x) + ) + cos cos( (y y) + sin($number) } ) + sin($number) } set sum [vector set sum [vector expr expr sum( sum(x x)] )]
Graph widgets accept vectors instead of Tcl lists for data.
Graphs automatically notified/redrawn when vector changes.
vector create vector create x x vector create vector create y y graph .g1 graph .g1 graph .g2 graph .g2 .g1 element create line1 .g1 element create line1 -
xdata x x -
ydata y y .g2 element create line1 .g2 element create line1 -
xdata x x -
ydata y y set set x x(0) 2.0 (0) 2.0 set set y y(0) 3.2 (0) 3.2
C API also exists for vectors.
Example: Load data from C.
Use two vector C API functions:
vector create vector create x x vector create vector create y y graph .g .g element create line1 -xdata x x -ydata y y … … LoadData LoadData x y x y
#include “ #include “tcl tcl.h” .h” #include “ #include “blt blt.h” .h” static int static int LoadDataCmd LoadDataCmd(ClientData clientData, Tcl_Interp *interp, int argc, char **arg (ClientData clientData, Tcl_Interp *interp, int argc, char **argv) v) { { Blt Blt_Vector * _Vector *xVec xVec, * , *yVec yVec; ; double *x, *y; double *x, *y; if ( if (Blt Blt_ _GetVector GetVector(interp, argv[1], & (interp, argv[1], &xVec xVec) != TCL_OK) { ) != TCL_OK) { return TCL_ERROR; return TCL_ERROR; } } if ( if (Blt Blt_ _GetVector GetVector(interp, argv[2], & (interp, argv[2], &yVec yVec) != TCL_OK) { ) != TCL_OK) { return TCL_ERROR; return TCL_ERROR; } } x = (double *) x = (double *)malloc malloc( (sizeof sizeof(double) * 1000); (double) * 1000); y = (double *) y = (double *)malloc malloc( (sizeof sizeof(double) * 1000); (double) * 1000); /* Fill the arrays */ /* Fill the arrays */ if ( if (Blt Blt_ _ResetVector ResetVector(interp, (interp, xVec xVec, x, 100, 1000, TCL_DYNAMIC) != TCL_OK) { , x, 100, 1000, TCL_DYNAMIC) != TCL_OK) { return TCL_ERROR; return TCL_ERROR; } } if ( if (Blt Blt_ _ResetVector ResetVector(interp, (interp, yVec yVec, y, 100, 1000, TCL_DYNAMIC) != TCL_OK) { , y, 100, 1000, TCL_DYNAMIC) != TCL_OK) { return TCL_ERROR; return TCL_ERROR; } } return TCL_OK; return TCL_OK; } } $UUD\VRIGRXEOHV HOHPHQWVXVHG HOHPHQWVLQDUUD\ DUJY>@LV[ DUJY>@LV\
Vector token really pointer to actual vector, not a copy (so be careful). Use macros to access vector fields:
#include “ #include “tcl tcl.h” .h” #include “ #include “blt blt.h” .h” static int static int GetDataCmd GetDataCmd(ClientData clientData, Tcl_Interp *interp, int argc, char **arg (ClientData clientData, Tcl_Interp *interp, int argc, char **argv) v) { { Blt Blt_Vector * _Vector *xVec xVec; ; double *x; double *x; int size, length, n; int size, length, n; if ( if (Blt Blt_ _GetVector GetVector(interp, argv[1], & (interp, argv[1], &xVec xVec) != TCL_OK) { ) != TCL_OK) { return TCL_ERROR; return TCL_ERROR; } } x = x = Blt Blt_ _VecData VecData( (xVec xVec); ); length = length = Blt Blt_ _VecLength VecLength( (xVec xVec); ); size = size = Blt Blt_ _VecSize VecSize( (xVec xVec); ); for (n = 0; n < length; n++) { for (n = 0; n < length; n++) { /* Do something with data */ /* Do something with data */ printf printf(“#%d is %f (“#%d is %f\ \n”, n, x[n]); n”, n, x[n]); } } printf printf(“There are %d free slots left (“There are %d free slots left\ \n”, size n”, size -
length); return TCL_OK; return TCL_OK; } } ,I\RXFKDQJHWKHDUUD\\RX PXVWFDOO%OWB5HVHW9HFWRU
Graph’s postscript
.g postscript configure .g postscript configure -
landscape yes -
maxpect yes yes .g postscript output .g postscript output myFile myFile. .ps ps
center yes
landscape yes
maxpect yes yes
decorations no
printer
Query printer settings with getattr
Adjust printer settings with setattr
set output [.g postscript output] set output [.g postscript output] set set pid pid [printer open {QMS [printer open {QMS ColorScript ColorScript 100 v49.4}] 100 v49.4}] printer write printer write $ $pid pid $output $output printer close printer close $ $pid pid set pid [printer open {QMS ColorScript 100 v49.4}] printer printer getattr getattr $ $pid pid myArray myArray puts “Paper size is puts “Paper size is $ $myArray myArray( (PaperSize PaperSize) )” ” puts “Page orientation is puts “Page orientation is $ $myArray myArray(Orientation) (Orientation)” ” set set myArray myArray( (PaperSize PaperSize) ) Letter Letter set set myArray myArray(Orientation) (Orientation) Landscape Landscape printer printer setattr setattr $ $pid pid myArray myArray printer write $pid $output printer close $pid
Graph has two Windows-specific print operations (still experimental).
print1
print2
set pid [printer open {QMS ColorScript 100 v49.4}] .g print1 .g print1 $ $pid pid printer close $pid set pid [printer open {QMS ColorScript 100 v49.4}] .g print2 .g print2 $ $pid pid printer close $pid
How do I tile graphs on a single a page?
New eps
canvas .c -width 6.75i -height 5.25i -bg white .c create .c create eps eps 10 620 10 620 -
file xy xy. .ps ps -
anchor sw sw .c create .c create eps eps 500 10 500 10 -
file g1.ps ps -
width 300 -
height 300 .c create .c create eps eps 500 320 500 320 -
file out.ps ps -
width 300 -
height 300 .c create text 20 200 -text "This is a text item" \
.c create rectangle 10 10 50 50 -fill blue .c create rectangle 50 50 150 150 -fill green -outline red
eps
But can also display EPSI preview image.
Better: use Tk photo image.
set set image image [image create photo] [image create photo] .g snap .g snap $image $image .g postscript output .g postscript output myFile myFile. .ps ps .c create .c create eps eps 500 10 500 10 -
file myFile myFile. .ps ps -
image $image $image
,PDJHRIJUDSKGUDZQLQWRSKRWR %HWWHUWKDQVQDSSLQJJUDSKZLQGRZ
Mirror axes. Virtual axes. Pens and weights. Controlling graph margins.
Can display more than 2 axes.
Elements, markers, and grids are
Mirror axes: Use axis
.g axis configure .g axis configure x2 y2 x2 y2 -
hide no .g element configure line1 .g element configure line1 -
mapx x2 x2 -
mapy y2 y2 .g marker configure .g marker configure myLine myLine -
mapx x2 x2 -
mapy y2 y2 .g grid configure .g grid configure -
mapx x2 x2 -
mapy y2 y2 set lx [.g axis limits set lx [.g axis limits x x] ] set set ly ly [.g axis limits [.g axis limits y y] ] .g axis configure .g axis configure x2 x2 -
min [lindex lindex $lx 0] $lx 0] -
max [lindex lindex $lx 1] $lx 1] .g axis configure .g axis configure y2 y2 -
min [lindex lindex $ $ly ly 0] 0] -
max [lindex lindex $ $ly ly 1] 1]
[ \ 5HWXUQVOLVWRIPLQDQGPD[OLPLWV
Graph also supports virtual
.g axis create .g axis create axis1 axis1 -
title “My Axis #1” -
limits “%g” \ \
limitscolor red red -
limitsshadow red4 red4 .g axis create .g axis create axis2 axis2 -
limits “%4.2f” -
limitscolor purple purple \ \
limitsshadow purple4 purple4 .g axis configure axis1 axis2 .g axis configure axis1 axis2 -
limitsfont {Helvetica 12} {Helvetica 12} .g element configure line1 .g element configure line1 -
mapy axis1 axis1 .g element configure line2 .g element configure line2 -
mapy axis2 axis2 .g .g xaxis xaxis use use axis1 axis1
Each element has its own default pen
Can create new pens and swap them in/out of elements. All elements use a standard “active” pen (activate
.g pen create .g pen create pen1 pen1 -
symbol circle -
color blue -
linewidth 2 2 .g pen create .g pen create pen2 pen2 -
symbol cross -
color red .g element configure line1 .g element configure line1 -
pen pen1 pen1 .g element configure line2 .g element configure line2 -
pen pen2 pen2 .g pen configure .g pen configure pen1 pen1 -
color yellow
(OHPHQWLVUHGUDZQZLWKQHZFRORU
.g pen configure .g pen configure activeLine activeLine -
linewidth 0 0 -
symbol square .g element configure .g element configure -
activepen pen1 pen1
Data elements can use more
Each element has a weight
.g pen create .g pen create pen1 pen1 -
color red -
symbol circle -
.g pen create .g pen create pen2 pen2 -
symbol none .g element configure line1 .g element configure line1 -
weight y y -
styles { { { {pen1 pen1 -
5 50} {pen2 pen2 100 175} { 100 175} {pen1 pen1 175 500} 175 500} } }
SHQ SHQ 'HIDXOWSHQ SHQ
Sometimes want to override computed values:
To determine current margin:
.g1 configure .g1 configure -
leftvariable left left trace variable left w trace variable left w UpdateMargins UpdateMargins proc proc UpdateMargins UpdateMargins { p1 p2 how } { { p1 p2 how } { global left global left .g2 configure .g2 configure -
leftmargin $left $left .g3 configure .g3 configure -
leftmargin $left $left .g4 configure .g4 configure -
leftmargin $left $left } }
Typical for applications to generate dozens of graphs.
Put graphs in tabbed notebook.
&OLFNLQJRQ[UHDWWDFKHVSDJH
Idea: Create index for graphs.
Thumbnails
Problem: How do you resize snapshot to arbitrary size?
set image [image create photo] .g snap .g snap $image $image set thumb [image create photo] $thumb copy $thumb copy $image $image -
subsample 4 4 4 4
VXEVDPSOH WKURXJK
winop
proc Thumbnail { graph w h } { proc Thumbnail { graph w h } { set set image image [image create photo] [image create photo] $graph snap $graph snap $image $image set set thumb thumb [image create photo [image create photo -
width $w -
height $h] winop winop resample resample $image $image $thumb $thumb box box box box image delete image delete $image $image return return $thumb $thumb } } set set nTabs nTabs [.t size] [.t size] for { set tab 0 } { $tab < $ for { set tab 0 } { $tab < $nTabs nTabs } { } { incr incr tab } { tab } { set graph [.t tab set graph [.t tab cget cget $tab $tab -
window] button .f.b$tab button .f.b$tab -
image [Thumbnail $graph 200 200] \ \
command [list .t invoke $tab .t invoke $tab ] ] table .f .f.b$tab $row,$ table .f .f.b$tab $row,$col col … … } }
0DNHVWDEVHOHFWHG
Executes programs while still handling events.
Example:
Callback proc invoked whenever data is available on stdout or stderr. set info [ set info [bgexec myVar bgexec myVar du $dir] du $dir]
VHWXVDJH>H[HFGXGLU@
text .text .text tag configure outTag -foreground green2 .text tag configure errTag -foreground red2 proc proc DrawStdout DrawStdout {data} { .text insert end $data {data} { .text insert end $data outTag
} proc proc DrawStderr DrawStderr {data} { .text insert end $data {data} { .text insert end $data errTag errTag } } bgexec myVar bgexec myVar -
\ myProgram myProgram & &
Makes widgets busy. Widgets ignore user-interactions.
Better than grab
Configurable cursor.
busy hold .frame busy hold .frame update busy release .frame busy release .frame
Transfers data between widgets
drag&drop source .sample drag&drop source .sample \ \
packagecmd { {PackageColor PackageColor %t} %t} drag&drop source .sample handler Color drag&drop source .sample handler Color drag&drop target .sample handler Color { drag&drop target .sample handler Color {ReceiveColor ReceiveColor %v} %v}
'UDJVRXUFH 'URSWDUJHWV 'URS WRNHQ
Hierarchical listbox widget.
Canvas, listbox, etc. Example: -
hierbox hierbox .h .h -
{AddEntries AddEntries %P} %P} \ \
closecommand {.h delete %n 0 end} {.h delete %n 0 end} proc proc AddEntries AddEntries { dir } { { dir } { if { [file if { [file isdirectory isdirectory $dir] } { $dir] } { eval eval .h insert end [ .h insert end [lsort lsort [glob $dir/*]] [glob $dir/*]] eval eval .h entry configure [ .h entry configure [lsort lsort [glob $dir/*/*] [glob $dir/*/*] \ \
button yes } } } } .h configure root .h configure root -
label “C:”
33DWKQDPHRIHQWU\ Q1RGHLQGH[RIHQWU\
Variety of styles supported.
Built-in search and selection functions.
set nodes set nodes [.h find [.h find -
glob -
name *.c] eval eval .h entry configure $nodes .h entry configure $nodes -
labelcolor red red .h find .h find -
glob -
name *.gif -
exec { .h entry configure %n .h entry configure %n \ \
image [image create photo -
file %P] } }
5HWXUQVOLVWRIPDWFKLQJQRGHV
Grid-based geometry manager.
table . table . \ \ 0,0 .label 0,0 .label -
cspan 2 2 \ \ 1,0 .text 1,0 .text -
fill both \ \ 1,1 . 1,1 .vs vs -
fill y \ \ 2,0 . 2,0 .hs hs -
fill x
Tabbed notebook widget.
tabset tabset .t .t -
bg red red -
scrollcommand {.s set} {.s set} scrollbar .s -command {. .t t view view} -orient horizontal .t insert end First .t insert end First -
window .t.graph \ \
selectcommand { { SelectTab SelectTab “First” } “First” } \ \
image [image create photo -
file book.gif] .t bind First <Enter> {ToolTips “Graph of Interpolating .t bind First <Enter> {ToolTips “Graph of Interpolating Splines Splines”} ”} .t bind First <Leave> {ToolTips “”} .t bind First <Leave> {ToolTips “”}
&DQXVHWDEVHW ZLWKRXWSDJHV
slant none
slant left
slant right
slant both
Variety of styles supported.
side top
side right
side bottom
side left
rotate 0
tiers 1
tiers 2
tiers 3
$WWDFKVFUROOEDUWRVLQJOHRUPXOWLWLHUHGWDEV
Can I use BLT in a commercial product?
Where do I get the latest version?
Where do I send bug reports and requests?
Books
What does BLT stand for?