1
Building Better Applications with BLT
George A. Howlett
Silicon Metrics Corporation Austin, Texas
Building Better Applications with BLT George A. Howlett - - PowerPoint PPT Presentation
Building Better Applications with BLT George A. Howlett Silicon Metrics Corporation Austin, Texas 1 What is BLT? Set of widgets and new commands. Extends the Tcl interpreter, no patching required. Features: Graph, stripchart,
1
Silicon Metrics Corporation Austin, Texas
2
Set of widgets and new commands.
Features:
…things I need for my Tcl/Tk applications.
Platforms:
3
How to plot data with the graph widget. Zooming and scrolling. Printing. Annotating graphs. Build your own zooming graph. Customizing the graph:
Interactive graphs. Data handling. Advanced features. Managing graphs with tabnotebooks.
4
Graph drawn on the canvas using Tcl code. Example in Tk widget demo. Problems:
No code for resizing.
5
Create graph widget and add data elements with element
.
symbol
Symbol displayed at each data point.
xdata
Real numbers representing X-coordinates.
ydata
Real numbers representing Y-coordinates. package require BLT blt::graph .g -title ”My Graph” pack .g .g .g element element create line1 create 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
6
Elements are a graph component.
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 … }
Legend
reflects depth.
7
Graph’s axis
Graph is automatically redrawn displaying the selected range.
min and -
max to the empty string to restore auto-scaling.
.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
3.0, 300.0 3.0, 300.0 1.0, 100.0 1.0, 100.0 3.0, 300.0 3.0, 300.0 1.0, 100.0 1.0, 100.0
.g axis configure x .g axis configure x -
min {} -
max {} .g axis configure y .g axis configure y -
max {} -
max {}
8
To scroll, add or subtract same amount from both min and max. Viewport
Scroll region
Scroll Region Viewport
.g axis configure x .g axis configure x – –min [ min [expr expr 1.0 + $delta] 1.0 + $delta] \ \
max [expr expr 3.0 + $delta] 3.0 + $delta]
9
scrollbar .hs scrollbar .hs -
command { .g axis view x .g axis view x } } -
scrollbar .vs -command { .g axis view y } -orient vertical .g axis configure x .g axis configure x -
scrollcommand { .hs set } { .hs set } .g axis configure y .g axis configure y -
scrollcommand { .vs set } { .vs set }
What if viewport and default scroll region overlap?
10
symbol circle
fill yellow
pixels 8
linewidth 0
dashes dot Lots and lots of element
Most don’t need to be set.
11
– –smooth step smooth step
label “My Label”
areapattern @ @hobbes hobbes. .xbm xbm
areatile $image $image
areapattern solid solid
showvalues y y
12
Both X and Y error bars can be displayed for elements.
xhigh, -
xlow, -
yhigh, -
ylow High/low sample for each data point.
xerror, -
yerror Defines delta for symmetric error range. .g element create s&p500 .g element create s&p500 -
symbol cross – –fill yellow fill yellow \ \
–linewidth linewidth 0 0 – –errorbarwidth errorbarwidth 2 2
x { 1 2 3 4 5 8 9 10 11 12 15 16 17 18 19 22 23 … } \ \
y { 989.82 968.65 948.09 953.99 989.03 976.98 … } \ \
yhigh { 994.46 968.65 954.30 989.07 993.56 979.63 … } { 994.46 968.65 954.30 989.07 993.56 979.63 … } \ \
ylow { 967.43 945.54 934.87 953.99 972.91 951.71 … } { 967.43 945.54 934.87 953.99 972.91 951.71 … }
13
Assorted options set appearance using axis
descending yes
rotate 90
title ”Y Axis”
ticklength -
5
loose yes
logscale yes
showticks no
hide yes Changes made on Y-axis
14
Tick
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
Don’t modify graph within callback proc.
15
Graph’s postscript
Other options control graph, border, and paper size. .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
16
Scenario #1: You have a PostScript printer BLT 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 [ [blt blt::printer open {QMS ::printer open {QMS ColorScript ColorScript 100 v49.4}] 100 v49.4}] blt blt::printer write ::printer write $ $pid pid $output $output blt blt::printer close ::printer close $ $pid pid blt blt::printer ::printer getattr getattr $ $pid pid myArray myArray set set myArray myArray( (PaperSize PaperSize) ) Letter Letter set set myArray myArray(Orientation) (Orientation) Landscape Landscape blt blt::printer ::printer setattr setattr $ $pid pid myArray myArray blt::printer write $pid $output blt::printer close $pid
17
Scenario #2: You have a non-PostScript printer. Graph has two Windows-specific print operations.
print1
print2
set pid [blt::printer open {QMS ColorScript 100 v49.4}] .g .g print2 print2 $pid blt::printer close $pid set pid [blt::printer open {QMS ColorScript 100 v49.4}] .g .g print1 print1 $pid blt::printer close $pid
18
metafile (EMF)
set image [image create photo] .g snap snap $image $image write file.gif –format GIF .g snap –format EMF CLIPBOARD
19
Markers
6 types of markers:
text
line
polygon
bitmap
image
window
.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}
Marker positions in graph coordinates.
20
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 {} } }
Can configure more than one axis at a time.
21
Create user-selectable zoom region. Drawn with a line marker.
Selects first corner of zoom region.
Draws outline. Position is opposite corner of region.
Deletes outline, zooms to selected region.
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 ButtonPress: Select 1st corner. ButtonRelease ButtonRelease: Select 2nd corner.
22
x0 and y0 y0.
xor option.
coords operation changes line coordinates.
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 } }
Markers without coordinates aren’t drawn. Name the marker, so we can refer to it.
$x0,$y0 $x0,$y0 $x,$y $x,$y
23
Why doesn’t example 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]
24
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 blt blt::busy hold $graph ::busy hold $graph update blt blt::busy release $graph ::busy release $graph } proc Unzoom { graph } { if { ![EmptyZoom] } { eval [PopZoom] } if { ![EmptyZoom] } { eval [PopZoom] } blt blt::busy hold $graph ::busy hold $graph update blt blt::busy release $graph ::busy release $graph }
Use Tcl list as zoom stack. Busy command prevents accidental zoom/unzoom.
25
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} } }
Get current axis ranges. Stack commands to restore to current zoom level. Pop last command
26
Controls position/appearance of legend.
graph graph legend legend configure configure ? ?option value...
?
position right
position left
position top
position bottom
position plotarea
hide yes
raised yes
position @450,100
27
Controls appearance of built-in grid.
hide no
color lightblue
dashes 0
mapy {}
mapx {}
minor no
28
Controls position/appearance of crosshairs.
dashes dash
position @450,100
hide no
color red
.g .g crosshairs crosshairs on
.g .g crosshairs crosshairs configure configure -
color red -
dashes 2 bind .g <Motion> { bind .g <Motion> { .g .g crosshairs crosshairs configure configure -
position @%x,%y } }
29
BLT has 3 graphing widgets available:
graph X-Y coordinate graph.
barchart Displays bars at X-Y coordinates.
stripchart Similar to X-Y graph, extra features.
Every feature we’ve seen so far works in all three widgets..
30
Zooming graph example of interactive graph. All graph widgets/plotting packages draw graphs.
Two-way communication (back annotation) lets graph become powerful tool.
31
Elements have closest
graph graph element element closest closest x x y y varName varName ? ?options
? ?elemName elemName…? …?
Writes information into a Tcl array variable.
name Name of closest element.
dist Distance from element.
index Index of closest data point.
x and y y The X-Y graph coordinates of the closest point.
Options:
halo Selects cut-off radius from screen coordinate.
interpolate Search for closest point on trace, not just data points.
along Search perpendicular to X or Y axis.
.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)” ”
Returns “1” if a closest element is found,
32
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]
Each component has its
bind operation.
33
How do you display many elements?
Let user interactively highlight elements.
legend entry.
34
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 } }
35
Both legend and elements have activate
When active:
activebackground color.
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 } }
36
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.
39 elements 361 x-values 361 y-values
Don’t they all have the same x-values?
37
Vector
Access data via either Tcl command or array variable.
Recognized by graph widgets.
blt blt::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) blt blt::vector create ::vector create x x blt blt::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
Variable by the same name as vector is also created New Tcl command by the same name as vector is created.
38
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.
blt blt::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
Can specify initial vector size. All values default to 0.0.
39
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 }
Kind of like “upvar”. Remaps the vector’s variable to the local variable “x”.
40
Vector’s expr
+ +-
* / ^
== != ! && || < > <= >= == != ! && || < > <= >=
abs abs acos asin atan acos asin atan ceil ceil cos cosh cos cosh exp floor exp floor hypot hypot log log10 sin log log10 sin sinh sqrt sinh sqrt tan tan tanh tanh
adev adev kurtosis length max mean median min kurtosis length max mean median min norm prod q1 q3 random round norm prod q1 q3 random round srandom sdev srandom sdev skew sort skew sort var var
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 [ set sum [blt blt::vector ::vector expr expr sum( sum(x x)] )]
41
Graph widgets accept vectors instead of Tcl lists for data.
Graphs automatically notified/redrawn when vector changes.
blt blt::vector create ::vector create x x blt blt::vector create ::vector create y y blt blt::graph .g1 ::graph .g1 blt blt::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
42
C API also exists for vectors.
Example: Load data from C.
LoadData to call vector C API.
Use two vector C API functions:
Blt Blt_ _GetVector GetVector Retrieves an existing vector. Blt Blt_ _ResetVector ResetVector Resets the vector data and notifies graphs.
blt blt::vector create ::vector create x x blt blt::vector create ::vector create y y blt::graph .g .g element create line1 -xdata x x -ydata y y … … LoadData LoadData x y x y
43
#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; } } Arrays of doubles. # elements used. # elements in array. argv[1] is “x” argv[2] is “y”
44
Vector token really pointer to actual vector, not a copy (so be careful). Use macros to access vector fields:
Blt_ _VecData VecData, , Blt Blt_ _VecLength VecLength, , Blt Blt_ _VecSize VecSize
#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; } } If you change the array, you must call Blt_ResetVector.
45
Tiling graphs. Multiple axes. Pens and weights. Controlling graph margins.
46
How do I tile graphs on a single a page?
BLT eps
not screen image.
canvas item.
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
47
eps
Can also display EPSI preview image.
Better: use Tk photo image.
eps item to display.
snap operation.
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
Image of graph drawn into photo. Better than snapping graph window.
48
x, y y, x2 x2, and y2 y2.
x2 and y2 y2 are hidden by default.
Elements, markers, and grids are
x and y y by default.
mapx and -
mapy switch axes.
.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
x2 y2
49
Want axes “x2” and “y2” to mirror “x” and “y” Problem: Data range is defined only on one set
Replicate the data ranges on the mirrored axes.
limits operation to get current axis range.
–scrollmin scrollmin, -
scrollmax if scrolling both axes.
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 -
scrollmin [ [lindex lindex $lx 0] $lx 0] \ \
scrollmax [ [lindex lindex $lx 1] $lx 1] .g axis configure .g axis configure y2 y2 -
scrollmin [ [lindex lindex $ $ly ly 0] 0] \ \
scrollmax [ [lindex lindex $ $ly ly 1] 1]
“x2” “y” “y2” “x”
50
Can also create virtual axes.
in plotting area.
Can replace normal axes with xaxis
use operation maps axis to margin.
.g .g axis axis create create axis1 axis1 -
title “My Axis #1” -
limits “%g” \ \
limitscolor red red -
limitsshadow red4 red4 .g .g axis axis create 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
51
.g axis create axis1 .g axis create axis1 – –title “temp” title “temp” .g axis create axis2 .g axis create axis2 – –title “volume” title “volume” .g axis create axis3 .g axis create axis3 – –title “work” title “work” .g axis create axis4 .g axis create axis4 – –title “Samples” title “Samples” .g axis create axis5 .g axis create axis5 – –title “pressure” title “pressure” .g axis create axis6 .g axis create axis6 – –title “power” title “power” .g .g yaxis yaxis use “axis1 axis2 axis3” use “axis1 axis2 axis3” .g y2axis use “axis4 axis5 axis6” .g y2axis use “axis4 axis5 axis6”
52
Pen component represents drawing style for an element.
Can create new pens and swap them in/out of elements. All elements use a standard “active” pen (activate
activeLine graph, stripchart widgets
activeBar barchart
.g .g pen pen create create pen1 pen1 -
symbol circle -
color blue -
linewidth 2 2 .g .g pen pen create 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 .g pen pen configure configure pen1 pen1 -
color yellow
Element is redrawn with new color.
.g .g pen pen configure configure activeLine activeLine -
linewidth 0 0 -
symbol square .g element configure .g element configure -
activepen pen1 pen1
53
Data elements can use more
Each element has a weight
weight option. Like -
xdata or
ydata options, takes vector or Tcl list.
styles option maps pens to data points according to weight value.
range.
.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} } }
pen2 pen1 Default pen. pen1
54
Margin sizes automatically calculated (based on axis values, etc.) Sometimes want to override computed values:
leftmargin, -rightmargin rightmargin, -
topmargin, and
bottommargin graph configuration options.
To determine current margin:
extents operation reports margin sizes.
leftvariable, etc. specify variables, set when margins are updated.
.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 } }
55
Typical for applications to generate dozens of graphs.
Put graphs in tabbed notebook.
Clicking on “x” reattaches page.
56
Tabbed notebook widget.
blt blt:: ::tabnotebook tabnotebook .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 \ \
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 “”}
Can use tabnotebook without pages.
57
slant none
slant left
slant right right
slant both
Variety of styles supported.
configuration options.
side top
side right
side bottom
side left
rotate 0
tiers 1
tiers 2
tiers 3 Attach scrollbar to single or multi-tiered tabs.
58
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
59
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] blt blt:: ::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 ] ] blt blt::table .f .f.b$tab $row,$ ::table .f .f.b$tab $row,$col col … … } }
Makes tab selected.
60
treeview widget. tree data object. bgexec command. busy. drag&drop. table geometry manager.
61
Supports incremental (lazy) insertions. Much faster than Tcl-based versions.
Multi-mode selection
Built-in search and selection functions.
62
Variety of styles supported.
(e.g. tool tips).
configurable for single entries.
Uses BLT tree data object.
63
Tree data object represents a general-ordered tree of data. Data is accessible through Tcl command or C API. Data can be shared among clients (e.g. treeview widget). set tree [ set tree [blt blt::tree create] ::tree create] proc proc LoadTree LoadTree { tree { tree parentNode parentNode dir } { dir } { set saved [ set saved [pwd pwd] ] cd cd $dir $dir foreach foreach f [glob *] { f [glob *] { set node [$tree insert $ set node [$tree insert $parentNode parentNode – –label $f] label $f] if { [file if { [file isdir isdir $f] } { $f] } { LoadTree LoadTree $tree $node $f $tree $node $f } } } } cd cd $saved $saved } } LoadTree LoadTree $tree 0 /etc $tree 0 /etc blt blt:: ::treeview treeview .t .t – –tree $tree tree $tree
64
Executes programs while still handling events.
fileevent.
Example:
myVar is set when program finishes.
myVar yourself terminates the program.
Callback proc invoked whenever data is available on stdout or stderr. set info [ set info [bgexec myVar bgexec myVar du $dir] du $dir]
set usage [exec du $dir]
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 } } blt blt:: ::bgexec myVar bgexec myVar -
\
&
65
Makes widgets busy. Widgets ignore user-interactions.
Better than grab
Configurable cursor.
blt blt::busy hold .frame ::busy hold .frame update blt blt::busy release .frame ::busy release .frame
66
Transfers data between widgets
send command.
source, drop target, or both.
CDE drag-and-drop.
blt blt::drag&drop source .sample ::drag&drop source .sample \ \
packagecmd { {PackageColor PackageColor %t} %t} blt blt::drag&drop source .sample handler Color ::drag&drop source .sample handler Color blt blt::drag&drop target .sample handler Color ::drag&drop target .sample handler Color \ \ { {ReceiveColor ReceiveColor %v} %v}
Drag source Drop targets Drop token
67
Grid-based geometry manager.
blt blt::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
0,0 0,0 1,1 1,1 2,0 2,0 1,0 1,0
68
What version of Tcl/Tk is required?
Can I use BLT in a commercial product?
Where do I get the latest version?
http://www.sourceforge sourceforge.net/projects/ .net/projects/blt blt/files /files
Where do I send bug reports and requests?
69
Books
edited by Mark Harrison.
by Paul Raines and Jeff Trantor.
What does BLT stand for?
Bacon, Lettuce, and Tomato Better Luck Tomorrow