Building User Interfaces With Tcl And Tk Michael Miller
[email protected]
The Tk Toolkit ◆
The problem:
◆
– Too hard to build applications with nice user interfaces. The wrong solution:
◆
– C++, object-oriented toolkits. – Only small improvement (10-20%?): must still program at a low level. The right solution: – Raise the level of programming. – Create interfaces by writing Tcl scripts.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 2
Creating User Interfaces With Tk ◆
Additional Tcl commands: – – – –
◆
Create Motif-like widgets. Arrange widgets. Bind events to Tcl commands. Manipulate X selection, focus, window manager, etc.
Library of C procedures: – Create new widget classes. – Create new geometry managers.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 3
What's A Tk-Based Application? ◆
The Tcl interpreter.
◆
The Tk toolkit.
◆
Application-specific C code (primitives!): – New object types. Tcl commands – New widgets.
◆
Tcl scripts (compose primitives): – Build user interface. – Respond to events.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 4
Wish: Windowing Shell ◆ ◆
Create user interfaces by writing Tcl scripts. Hello, world: button .hello -text "Hello, world" -command exit pack .hello
◆ ◆ ◆
Simple directory browser: 30 lines Web browser: 2000 lines 10x less code for simple things.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 5
Outline ◆ ◆ ◆ ◆ ◆ ◆
Basic structures: windows, widgets, processes. Creating widgets: class commands. Widget commands. Geometry management: the placer, packer, and grid. Bindings. Other commands: send, focus, selection, window manager, grabs.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 6
Structure Of A Tk Application ◆
Widget hierarchy.
◆
One Tcl interpreter.
◆
One process (can have > 1 application in a process).
◆
Widget: a window with a particular look and feel.
◆
Widget classes implemented by Tk: Frame Menubutton Canvas Label Menu Scrollbar Button Message Scale Checkbutton Entry Listbox Radiobutton Text Toplevel
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 7
The Widget Hierarchy .frame
.frame.l .frame. .frame.h abel v .frame.lis tbox
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 8
Types Of Windows
Main window .listbox
Internal windows
.
.menu
.menu.file
Tcl/Tk Tutorial: Tk Scripting
.scroll
.menu.help
Top-level window .dlg
.dlg.msg .dlg.no .dlg.yes August 4, 1997, slide 9
Creating Widgets ◆
Each widget has a class: button, listbox, scrollbar, etc.
◆
One class command for each class, used to create instances: button .a.b -text Quit -command exit scrollbar .x -orient horizontal
class name
configuration options
window name
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 10
Configuration Options ◆
Defined by class. For buttons: -activebackground -activeforeground -anchor -background -bitmap -borderwidth -command -cursor
-disabledforeground -font -foreground -height -highlightbackground -highlightcolor -highlightthickness -image
-justify -underline -padx -width -pady -wraplength -relief -state -takefocus -text -textvariable
◆
If not specified in command, taken from option database: –From RESOURCE_MANAGER property or .Xdefaults. –May be set, queried with option command.
◆
If not in option database, default provided by class. –option add *Button.background forestgreen
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 11
Widget Commands ◆
Tcl command for each widget, named after widget.
◆
Used to reconfigure, manipulate widget: button .a.b .a.b configure -relief sunken .a.b flash scrollbar .x .x set 0.2 0.7 .x get
◆
Widget command is deleted when widget is destroyed.
◆
Principle: all state should be readable, modifiable, anytime.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 12
Geometry Management ◆
◆
◆
Widgets don't control their own positions and sizes: geometry managers do. Widgets don't even appear on the screen until managed by a geometry manager. Geometry manager = algorithm for arranging slave windows relative to a master window.
Tcl/Tk Tutorial: Tk Scripting
Parameters from application designer Requested size from slave
Geometry of master
Geometry Manager
Size and location of slave
Requested size for master
August 4, 1997, slide 13
The Placer ◆ ◆ ◆ ◆ ◆
Simple but not very powerful. Each slave placed individually relative to its master. The first geometry manager. Useful for widgets needing percentage based sizes. Example: paned windows.
place $w -in $parent -relwidth 0.5 -relheight 0.5 \ -relx 0.5 -rely 0.5
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 14
The Packer ◆ ◆ ◆ ◆
More powerful than the placer. Arranges groups of slaves together (packing list). Packs slaves around edges of master's cavity. For each slave, in order:
1. Pick side of cavity.
3. Optionally grow slave to fill parcel.
2. Slice off parcel for slave.
4. Position slave in parcel.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 15
The Packer: Options ◆
Padding
◆
– -ipadx or -ipady for internal, -pady or -padx otherwise. Expanding
◆
– -expand 1 to fill when resized Filling
◆
– -fill {x,y,both} to show which way to expand. Anchoring
◆
– -anchor {n,w,s,e,ne,nw,center} widget. Sides – -side {left,right,top,bottom} to another widget
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 16
A Scrolled Listbox with pack proc scroll_list {w name} { frame $w label $w.label -text "$name" -anchor w scrollbar $w.v -command "$w.listbox yview" scrollbar $w.h -orient horizontal -command "$w.listbox xview" listbox $w.listbox \ -xscrollcommand "$w.h set" -yscrollcommand "$w.v set" pack $w.v -side right -fill y -pady 19 pack $w.h -side bottom -fill x pack $w.label -fill x -anchor w -ipadx 2 pack $w.listbox -expand 1 -fill both return $w } pack [scroll_list .f "f list"] -expand 1 -fill both
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 17
The Grid Control ◆ ◆
◆ ◆
◆
Layout with rows and columns. Use -weight 0 or 1+ to set growth region. – 0 means does not want more space – 1 means take more space then 0 Use -sticky {snew} to place widget in grid box. Can use -rowspan or -columnspan to make more irregular shapes. Use rowconfigure and column configure with weight.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 18
A Scrolled Listbox with grid proc scroll_box {w name} { frame $w label $w.label -text "$name" -anchor w scrollbar $w.v -command "$w.listbox yview" scrollbar $w.h -orient horizontal -command "$w.listbox xview" listbox $w.listbox \ -xscrollcommand "$w.h set" -yscrollcommand "$w.v set" grid rowconfigure $w 1 -weight 1 grid columnconfigure $w 0 -weight 1 grid config $w.label -sticky snew grid config $w.listbox $w.v -sticky snew grid config $w.h -sticky snew return $w } pack [scroll_box .b "b list"] -expand 1 -fill both Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 19
Callbacks ◆
◆
How to make widgets work together with application, other widgets? Tcl scripts. Widget actions are Tcl commands: button .a.b -command exit
◆
Widgets use Tcl commands to communicate with each other: scrollbar .s -command ".text yview"
◆
Application uses widget commands to communicate with widgets. Above command results in: .text yview scroll 1 unit
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 20
Bindings ◆
Associate Tcl scripts with X events: bind .b
{backspace .t} Window(s)
◆
Event
Script
Use tags to select one or more windows: – Name of window: .b – Widget class: Text – All windows: all – Arbitrary string: foo, bar, ...
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 21
Bindings: Specifying Events ◆
Specifying events: Modifiers
Event Type
Button or Keysym
<3> a
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 22
Bindings: Substitutions ◆
◆
% substitutions in binding scripts: – Coordinates from event: %x and %y. – Window: %W. – Character from event: %A. – Many more... Examples: bind .c {move %x %y} bind .t {insert %A} bind all {help %W}
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 23
Binding Order ◆
What if multiple bindings match an event? bind .t a ... bind all ...
◆
One binding triggers per tag: most specific.
◆
Default order of tags: widget, class, toplevel, all.
◆
Can change tags with bindtags command: bindtags .b {MyButton .b foo all}
◆
Can use break to skip later tags.
◆
Note: these rules apply only to Tk 4.0 and later.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 24
More On Bindings ◆
Text and canvas widgets support bindings internally: – Associate tags with text or graphics: .t tag add foo 1.0 2.0 .c create rect 1c 1c 2c 2c -tags foo – Associate bindings with tags: .t bind foo <1> {...} .c bind foo <Enter> {...}
◆
Bindings always execute at global level: – If binding created in procedure, procedure's local variables aren't available at event-time.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 25
Quoting and Scope ◆
◆ ◆
Often want binding script to use some information from binding-time, some from event-time. Use list commands to generate scripts. Use procedures to separate event-time information from bind-time information. bind .x <1> {set y [expr $a + $b]}
Wrong
Right
Use bind-time value bind .x <1> "set y [expr $a + $b]"
Use event-time value
proc sety a { global b y set y [expr $a + $b] } bind .x <1> [list sety $a]
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 26
Other Tk Commands ◆
The selection: selection get selection get FILE_NAME
◆
Issuing commands to other Tk applications: send tgdb "break tkEval.c:200" winfo interps => wish tgdb ppres
◆
Window information: winfo width .x winfo children . winfo containing $x $y
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 27
Access To Other Window Facilities ◆
Keyboard focus: focus .x.y
◆
Communication with window manager: wm title . "Editing main.c" wm geometry . 300x200 wm iconify .
◆
Deleting windows: destroy .x
◆
Grabs: grab .x grab release .x
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 28
disk in operation:
Windows 95 df utility: http://www.itribe.net/virtunix/files/unix95.7.zip
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 29
Code : disk #!/bin/sh # \ exec wish4.2 $0 $* # build two labels side by side in a frame proc vlabel {w text var} { frame $w label $w.label -width 7 -text $text -anchor e label $w.value -width 7 -text $var -anchor e pack $w.label $w.value -side left return $w } proc clabel {w text bg var} { frame $w label $w.color -width 5 -height 5 -bitmap gray50 -bg $bg -fg $bg label $w.label -width 4 -text $text -anchor w label $w.value -width 7 -text $var -anchor e pack $w.color -padx 2 -side left pack $w.label $w.value -side left return $w }
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 30
Build a disk # build 4 label groups and a canvas with two blank arcs # put canvas widget and arc tags in array proc gui_disk {w i} { global disk pack [frame $w -relief sunken -bd 3] frame $w.stat canvas $w.view -width 71 -height 41 pack $w.stat $w.view pack [label $w.stat.name -text "-" -fg white -bg blue] -anchor n pack [vlabel $w.stat.cap Disk -] -anchor n $w.stat.cap.value configure -anchor c $w.view create arc 3 3 70 40 -fill black -start 0 -extent 359 pack [clabel $w.stat.used "Used" grey50 -] -anchor n pack [clabel $w.stat.free "Free" forestgreen -] -anchor n set r [$w.view create arc 3 3 69 38] set b [$w.view create arc 3 3 69 38] set disk(c$i) "$w $r $b" return $w }
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 31
Put percentages and labels # calculate arc full and arc empty # set label values # set arc values and color proc fill_disk {i} { global disk set nick [expr [string length [lindex $disk($i) 1]] -2] set pct [string range [lindex $disk($i) 1] 0 $nick] set full [expr $pct.0 / 100.0 * 360] set emp [expr 360 - $full] set w [lindex $disk(c$i) 0] set r [lindex $disk(c$i) 1] set b [lindex $disk(c$i) 2] $w.stat.name configure -text [lindex $disk($i) 0] $w.stat.cap.value configure -text [lindex $disk($i) 1] $w.stat.cap.label configure -text [lindex $disk($i) 4] $w.stat.used.value configure -text [lindex $disk($i) 2] $w.stat.free.value configure -text [lindex $disk($i) 3]
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 32
Percentages continued $w.stat.free.color configure -fg forestgreen -bg forestgreen $w.view itemconfigure $r -fill grey50 -start 180 -extent $full set full [expr $full + 180] $w.view itemconfigure $b -fill forestgreen -start $full -extent $emp if {$pct > 89} { $w.view itemconfigure $b -fill yellow $w.stat.free.color configure -fg yellow -bg yellow } if {$pct > 97} { $w.view itemconfigure $b -fill red $w.stat.free.color configure -fg red -bg red } }
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 33
Check disk usage # check df and place each line entry in an array proc df_check {} { global disk set df [exec df -T] ;# for Linux, gives file type set i 0 while {[string length $df] > 1} { set n [string first "\n" $df] if {$n == -1} { set n [string length $df] } set line [string range $df 0 $n] set df [string range $df [expr $n +1] end] set FILE_TYPE [lindex $line 1] set USED_BLKS [lindex $line 3] set FREE_BLKS [lindex $line 4] set PERCENT [lindex $line 5] set PARTITION [lindex $line 6] set disk($i) "$PARTITION $PERCENT $USED_BLKS $FREE_BLKS $FILE_TYPE"
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 34
Checking continued if {$i != 0} { # skip title line if {[winfo exists .w$i] == 0} { pack [gui_disk .w$i $i] -side left } fill_disk $i } incr i } after 10000 df_check }
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 35
Start Program # set title and start program wm title . "Filesystems - 1024K blocks" df_check
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 36
Summary ◆
Creating interfaces with Tk is easy:
◆
– Create widgets. – Arrange with geometry managers. – Connect to application, each other. Power from single scripting language: – – – – –
For specifying user interface. For widgets to invoke application. For widgets to communicate with each other. For communicating with outside world. For changing anything dynamically.
Tcl/Tk Tutorial: Tk Scripting
August 4, 1997, slide 37