Peter Berger wrote: > I have been charged with the task of presenting data. I recieve a list in > alphabetical order such as: a b c d e f g h i j, and need to present it in a > dialog and organized in rows or columns such as: > a e i > b f j > c g > d h > If the dialog expands the number of columns should increase. Currently I > use this code: > > pack [text .text -wrap word -tabs "1.25i left" -setgrid 0] > set alist "apple bear cow dear elephant fine grape hello idol" > foreach a $alist {.text insert end "$a\t"} > > but this orginizes data as: > a b c > d e ... > Anyone have any ideas on how I can switch to the other format? ''KBK'' replies (20 Feb 2001): Are you really trying, instead, to do a multi-column [listbox]? If so, then [Bwidget] and [Tix] both have them, and you should probably just pick up one of them. ''([DKF]: In [Tk 8.5] or [Tile], you can also use the [ttk::treeview] widget.)'' If you really need multi-column display in a [text] widget, read on... I started to code this, and it turned out to be more interesting than I thought. I assume that you don't know the height of the text in advance, so you have to bind to the '''''' event and adjust your columns on the fly. The code I came up with is shown below. Check out what happens when you resize the window. ---- # Schedule to lay out the columns of the text from the idle loop proc repackWhenIdle { w args } { variable repackPending if { ! [info exists repackPending($w)] } { set repackPending($w) {} after idle [list [namespace code repack] $w] } return } # Lay out the columns of the text. proc repack { w } { variable repackPending variable list # Reset the flag that keeps this from being repeat-scheduled. catch { [unset repackPending($w)] } # Clear the old content of the widget $w configure -state normal $w delete 1.0 end # Calculate number of lines to display set lineHeight [font metrics [$w cget -font] -linespace] set textHeight [expr { [winfo height $w] - 2 * [$w cget -borderwidth] }] set numLines [expr { int( $textHeight / $lineHeight ) }] # Bail out if the widget is too small to display anything if { $numLines < 1 } { return } # Insert the requisite number of newlines, plus one for { set i 0 } { $i < $numLines } { incr i } { $w insert end \n {} } # Build up the list, in columns set line 1 set sep {} foreach item $list { incr line $w insert "${line}.0-1c" $sep {} $item {} if { $line > $numLines } { set line 1 set sep "\t" } } # Delete the excess newline $w delete end-1l end $w configure -state disabled return } # Set up the text grid [text .t \ -state disabled \ -wrap none \ -font {Helvetica 12} \ -width 40 -height 7 \ -tabs {1.25i left} ] \ -sticky nsew grid rowconfigure . 0 -weight 1 grid columnconfigure . 0 -weight 1 # Arrange to repack the text when either the text geometry or the # list content changes trace variable list w [list repackWhenIdle .t] bind .t [list repackWhenIdle %W] # Set initial content of the list set list { apple blackberry blueberry cherry grape grapefruit kiwi kumquat lemon nectarine orange peach pear plum prune raisin raspberry strawberry tangerine } ---- [WJG] (28/Jan/10) This is a simple solution that I came up with. With a little adjustment it could be adapted to become a stand-alone proc. ====== #!/bin/sh # the next line restarts using tclsh \ exec tclsh "$0" "$@" #--------------- package require Gnocl set txt1 [gnocl::text] gnocl::window -child $txt1 -defaultWidth 320 -defaultHeight 200 set data {a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} set rows(max) 6 set r 0 ;# row counter # initialise array to hold output strings for {set i 0 } {$i < $rows(max) } {incr i} { set rows($i) {} } # build up the output strings for {set i 0} {$i < [llength $data] } {incr i} { set rows($r) "$rows($r)\t[lindex $data $i]" incr r if {$r == $rows(max) } {set r 0} } # insert into the text for {set i 0 } {$i < $rows(max) } {incr i} { $txt1 insert end $rows($i)\n } ====== And this is what it produces: [http://lh6.ggpht.com/_yaFgKvuZ36o/S2IZn5HoDXI/AAAAAAAAAN0/psR2JKiNa3g/s800/Screenshot-columns.tcl.png] [WJG] Reworked this whilst drinking my first cup of tea of the (working) day. Here's it in proc form. It will return a list of the strings which can be subsequently inserted or processed elsewhere. The leading tabs on the first column are not included which, of course, can be added if needed on insertion. ====== #!/bin/sh # the next line restarts using tclsh \ exec tclsh "$0" "$@" #--------------- package require Gnocl # args: # data = list items to be formatted into colums # nrow = maximum number of rows to produce # returns # list of formatted row strings # note # tcl only proc tabulate_Columns {data nrows} { set r 0 ;# row counter set str {} ;# list contain final, formatted list, returned by proc # initialise an array to hold output strings for {set i 0 } {$i < $nrows } {incr i} { set rows($i) {} } # build up the output strings for {set i 0} {$i < [llength $data] } {incr i} { if {$rows($r) == {} } { set rows($r) "[lindex $data $i]" } else { set rows($r) "$rows($r)\t[lindex $data $i]" } incr r if {$r == $nrows } {set r 0} } # insert int the text for {set i 0 } {$i < $nrows } {incr i} { lappend str $rows($i) } return $str } # the uniquitous demo script set txt1 [gnocl::text] gnocl::window -child $txt1 -defaultWidth 320 -defaultHeight 200 set data {a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} foreach row [tabulate_Columns $data 5] { $txt1 insert end ${row}\n } ====== ---- !!!!!! %| [Category GUI] |% !!!!!!