JayBy 2016-07-06
For my dartscript, I use labels outside of a frame. Here is an extended version. I wrote this especially for scrolledframes. With a scrolledframe the header row and index column can scroll with the scrolled body.
If used with a scrolledframe, the head and index frames have to be also a scrolledframe. It's written for scrolledframe 0.9.1 (KJN optimized & enhanced version).
The procedures for head row / index column in gridLabels.tcl:
#****************************************************************************** # GridLabels # # Procedures for creating labels outside a gridded scrolledframe: # (used with scrolledframe 0.9.1 (KJN optimized & enhanced version)) # # $HF = Path of (inner) head frame # $IF = Path of (inner) index frame # $BF = Path of (inner) body frame # Head labels = ${HF}.head0, ${HF}.head1, ... # Index labels = ${HF}.index0, ${HF}.index1, ... #------------------------------------------------------------------------------ # Scrolled Frame # #--- GridHead ---------------------------------------------- # Configure (scrollable) head frame # - Create head labels, if necessary # - Place head labels # - Scrolls head frame, if it's a scrolledframe # Args: Inner HeadFrame, inner BodyFrame, ?-scroll <Bool>? # -scroll = Is headframe a scrolledframe or not? proc gridHead {HF BF args} { set H 0 # $HF is scrollable ? if {[regexp -- {.scrolled$} $HF]} { set S "true" } else { set S "false" } foreach {O V} $args { if {$O == "-scroll"} { set S $V } } # How many Cols ? lassign [grid size $BF] Cols Rows #--- Configure head labels for {set c 0} {$c < $Cols} {incr c} { # Create Head<Nr>, if not exists if {[winfo exists ${HF}.head$c] == 0} { ttk::label ${HF}.head$c -text "Head $c" -style Grid.TLabel -anchor c } # Set Width + Pos lassign [grid bbox $BF $c 0] x y w h place ${HF}.head$c -x $x -y 0 -width $w # Set Height set h [winfo reqheight ${HF}.head$c] if {$h > $H} {set H $h} } #--- Configure height # Uniform height of heads foreach l [winfo children $HF] { place configure $l -height $H } # Create height of (outer) frame $HF configure -height $H if {[string is true $S]} { [winfo parent $HF] configure -height $H #--- Scroll position set w [winfo width [winfo parent $BF]] set x [winfo x $BF] place $HF -x [expr $x + 1] -width [expr [string trim $x -] + $w] } } #--- GridIndex --------------------------------------------- # Configure (scrollable) index frame # - Create index labels, if necessary # - Place index labels # - Scrolls index frame, if it's a scrolledframe # Args: Inner IndexFrame, inner BodyFrame, ?-scroll <Bool>? # -scroll = Is indexframe a scrolledframe or not? proc gridIndex {IF BF args} { set W 0 # $IF is scrollable ? if {[regexp -- {.scrolled$} $IF]} { set S "true" } else { set S "false" } foreach {O V} $args { if {$O == "-scroll"} { set S $V } } # How many Rows ? lassign [grid size $BF] Cols Rows #--- Configure index labels for {set r 0} {$r < $Rows} {incr r} { # Create Index<Nr>, if not exists if {[winfo exists ${IF}.index$r] == 0} { ttk::label ${IF}.index$r -text "Idx $r" -style Grid.TLabel -anchor c } # Set Height + Pos lassign [grid bbox $BF 0 $r] x y w h place ${IF}.index$r -x 0 -y $y -height $h # Set Width set w [winfo reqwidth ${IF}.index$r] if {$w > $W} {set W $w} } #--- Configure width # Uniform width of index foreach l [winfo children $IF] { place configure $l -width $W } # Create width of (outer) frame $IF configure -width $W if {[string is true $S]} { [winfo parent $IF] configure -width $W #--- Scroll position set h [winfo height [winfo parent $BF]] set y [winfo y $BF] place $IF -y [expr $y + 1] -height [expr [string trim $y -] + $h] } }
A demo script:
#****************************************************************************** # Gridded Scroll Demo # # Demonstrate usage of gridLabels in a scrolled frame. # Using scrolledframe 0.9.1 (The KJN optimized & enhanced version) # lappend auto_path [file normalize [file join [file dirname [info script]] .. lib]] package require Tk package require scrolledframe source [file join [file dirname [info script]] gridLabels.tcl] #------------------------------------------------------------------------------ # Main # wm geometry . 600x400 #--- Head Frame -------------------------------------------- # Outer frame set HeadFrame0 [scrolledframe::scrolledframe .headframe \ -fill both \ ] # Inner frame set HeadFrame ${HeadFrame0}.scrolled #--- Index Frame ------------------------------------------- # Outer frame set IndexFrame0 [scrolledframe::scrolledframe .indexframe \ -fill both\ ] # Inner frame set IndexFrame ${IndexFrame0}.scrolled #--- BodyFrame --------------------------------------------- set BodyFrame0 [scrolledframe::scrolledframe .bodyframe \ -yscrollcommand ".vscroll set" \ -xscrollcommand ".hscroll set" \ -fill both \ ] set BodyFrame ${BodyFrame0}.scrolled set VScroll [ttk::scrollbar .vscroll -command "$BodyFrame0 yview"] set HScroll [ttk::scrollbar .hscroll -command "$BodyFrame0 xview" \ -orient horizontal] # Gridded layout for {set r 0} {$r < 10} {incr r} { for {set c 0} {$c < 10} {incr c} { set Cell($r,$c) [ttk::frame ${BodyFrame}.cell-$r-$c -padding 10 -relief sunken] set Label($r,$c) [ttk::label $Cell($r,$c).label-$r-$c -text "Label $r/$c"] set Entry($r,$c) [ttk::entry $Cell($r,$c).entry-$r-$c -width 10 -justify c] $Entry($r,$c) insert 0 "Value $r/$c" grid $Cell($r,$c) -column $c -row $r -sticky nswe pack $Label($r,$c) -anchor w pack $Entry($r,$c) } } #--- Configure --------------------------------------------- ttk::style configure Grid.TLabel -borderwidth 1 -relief raised -padding 2 grid $HeadFrame0 -column 1 -row 0 -sticky nswe grid $IndexFrame0 -column 0 -row 1 -sticky nswe grid $BodyFrame0 -column 1 -row 1 -sticky nswe grid $VScroll -column 2 -row 1 -sticky ns grid $HScroll -column 1 -row 2 -sticky we grid columnconfigure $HeadFrame all -weight 1 grid rowconfigure $IndexFrame all -weight 1 grid columnconfigure $BodyFrame0 all -weight 1 grid columnconfigure $BodyFrame all -weight 1 grid rowconfigure $BodyFrame0 all -weight 1 grid rowconfigure $BodyFrame all -weight 1 grid columnconfigure . 1 -weight 1 grid rowconfigure . 1 -weight 1 #--- Bind procs (with inner scrollable frames) ------------- bind . <Configure> {+ gridHead $HeadFrame $BodyFrame gridIndex $IndexFrame $BodyFrame }