17feb04 [jcw] - The following code is a quick experiment to explore the use of a virtual grid to show potentially huge amounts of data without having to copy them into the GUI. This "data aware widget" approach would work well with databases (and an upcoming package called Ratcl). The key idea is to maintain a grid of widgets that is twice the number of widgets displayed in both dimensions. Then, scrolling can reassign the "allocation" of each widget to the cell it currently represents. IOW, widgets stay on a canvas, caching the ones that are visible (plus a few more), and a window moves around, creating the illusion of moving over a huge virtual grid of widgets. By not creating widgets all the time, and by not even moving them around on the canvas, we get the benfit of Tk's double-buffering to cache visual detail and reduce the number of callbacks. In the image below, the arrows indicate reassignment of widgets, not movement or copying: [http://www.equi4.com/images/virtual-scroll.png] And here's code that places widgets on a canvas. It does not scroll yet, it's not more than a very first start at creating such a widget: package require Tk proc celldef {w px py} { label $w -anchor w \ -text "($px,$py) [string repeat . [expr {$px+$py}]]" } proc ginit {w rows cols} { global cells$w for {set y 0} {$y < $rows} {incr y} { set cmd grid for {set x 0} {$x < $cols} {incr x} { set cell $w.$x,$y celldef $cell $x $y lappend cmd $cell set cells${w}($x,$y) -1,-1 } eval [lappend cmd -sticky nsew -row $y] grid rowconfig $w $y -uniform a } for {set x 0} {$x < $cols} {incr x} { grid columnconfig $w $x -uniform a } } proc gconf {w} { $w.c configure -scrollregion [grid bbox $w.c.f] } proc gview {w} { frame $w scrollbar $w.h -command "$w.c xview" -orient horiz scrollbar $w.v -command "$w.c yview" canvas $w.c -xscrollcommand "$w.h set" -yscrollcommand "$w.v set" pack $w -expand 1 -fill both grid rowconfig $w 0 -weight 1 -minsize 0 grid columnconfig $w 0 -weight 1 -minsize 0 grid $w.c -row 0 -column 0 -sticky news grid $w.v -row 0 -column 1 -sticky news grid $w.h -row 1 -column 0 -sticky news bind $w "gconf $w" frame $w.c.f $w.c create window 0 0 -window $w.c.f -anchor nw return $w.c.f } ginit [gview .f] 10 6 Feel free to use, re-use, alter, extend, and/or comment as you like. ---- [D. McC]: How would this compare with a set of multi-scrolling listboxes using the -listvariable option, which could be vertically scrolled and horizontally gridded or un-gridded as needed? More, less, or equally efficient? ''I'm not sure. I think that's how Maurice Ulis's virtual listbox works. Listvariable's don't reduce the copying requirements though, if I understand them properly. You still need to hold all N data items in a Tcl list.'' ''One reason to explore the above approach is that each cell can contain a widget of arbitrary complexity. -[jcw]'' [NEM] This kind of reminds me of techniques used in side-scrolling platform games like the original Mario, where the background is made up of a grid of cells of a fixed size. The game draws enough cells to fill the screen, plus a border of cells around the edges. As the view moves to the right (say), the cells that disappear off the screen are deleted, while new cells are added on the other side. The difference here is that the cells (widgets) remain the same, we just re-assign their contents as the user scrolls. Interesting. [KPV] A similar technique is used in [Hack-O-Matic] to speed up the display of what appears to the user to be a scollable display of 32K x 8 widgets. ---- [[ [Category GUI] | [Category Widget] ]]