Donal Fellows (originally in the
Bag of Tk algorithms)
# Make our contents and a list of frame names...
for {set i 0} {$i<15} {incr i} {
set w .lb$i
frame $w
listbox $w.lb -xscrollcommand "$w.x set" -yscrollcommand "$w.y set"
scrollbar $w.x -command "$w.lb xview" -takefocus 0 -width 10 \
-orient horizontal
scrollbar $w.y -command "$w.lb yview" -takefocus 0 -width 10
$w.lb insert end "LISTBOX $i" "A: This is listbox $i" \
"B: This is listbox $i" "C: This is listbox $i" \
"D: This is listbox $i" "E: This is listbox $i"
grid $w.lb $w.y -sticky nsew
grid $w.x -sticky ew
grid columnconfigure $w 0 -weight 1
grid rowconfigure $w 0 -weight 1
lappend lbs $w
}
# How many frames to show at once?
set width 4
# Our primary scrollbar
scrollbar .sb -command "doScroll" -orient horizontal -width 20
# And set up the static parts of the geometry manager
grid .sb -row 1 -columnspan $width -sticky ew
for {set i 0} {$i<$width} {incr i} {
grid columnconfigure . $i -weight 1
after idle grid columnconfigure . $i -minsize \[winfo reqwidth .lb0]
}
grid rowconfigure . 0 -weight 1
after idle grid rowconfigure . 0 -minsize \[winfo reqheight .lb0]
# We start at the left...
set pos 0
proc reconf {} {
global pos lbs width
.sb set [expr {double($pos)/([llength $lbs])}] \
[expr {double($pos+$width)/([llength $lbs])}]
eval grid forget $lbs
eval grid [lrange $lbs $pos [expr {$pos+$width-1}]] -row 0
}
proc Xscroll {n units} {
global pos width
switch $units {
units {incr pos $n}
pages {incr pos [expr {$n*$width}]}
}
}
proc Xmoveto {fraction} {
global pos lbs
set pos [expr {int([llength $lbs]*$fraction)}]
}
proc doScroll {args} {
global pos lbs width
set oldpos $pos
set len [expr {[llength $lbs]-$width}]
eval X$args
if {$pos<0} {set pos 0} elseif {$pos>$len} {set pos $len}
if {$pos != $oldpos} {reconf}
}
# Set up the scrollbar and frames...
reconf
Also see
Virtual Scrolling for another solution that does not use text or canvas.