[JHJL] Here is a Snidget to create a collapsible label frame. It allows the user to click the frame's label to collapse/expand the frame (ie hide its contents and recover most of the space). The embedded child site frame can floated into its own toplevel (you might want to use a key binding for this...) ====== package require snit package require Tk package require Ttk snit::widget CollapsibleLabelFrame { # # We are basically wrapping a ttk::labelframe by attaching a # label and embedding a child site frame. # # The label is used so that we can bind to it to determine # when the user clicks it # # The embedded child site frame is a plain Tk frame (not ttk::frame) # because (for my application) one cannot use wm manage on a # ttk::frame # # Initial state 'open' or 'closed' # option -state \ -type { snit::enum -values {open closed} } -default open \ -configuremethod CFG-ChangeState \ -readonly 1 # # Text to display # option -text -configuremethod CFG-LabelText -default "" option -floattitle -default "" component lframe component label component frame delegate option -labelfont to label as -font delegate option -labelfg to label as -foreground # # I'm using symbol characters within the font so that I don't # have to worry colour. The downside is that the developer # can choose a font that doesn't have these symbols... # # Because the attached label is a ttk::label, one could use a # compound label + text and just manage the icon, but then # what colour icon to use and what style for the current theme # variable open_symbol "\u25bc" variable closed_symbol "\u25ba" variable text "" variable ginfo [list] variable floatheight 100 variable floatwidth 300 constructor {args} { install lframe using ttk::labelframe $win.lframe install label using ttk::label $lframe.label \ -textvariable [myvar text] \ -font {arial 11 bold} \ -foreground blue $lframe configure -labelwidget $label install frame using frame $lframe.frame -borderwidth 0 bind $label <1> [mymethod toggle] grid $frame -sticky news grid columnconfigure $frame 0 -weight 1 grid rowconfigure $frame 0 -weight 1 grid $lframe -sticky news grid columnconfigure $lframe 0 -weight 1 grid rowconfigure $lframe 0 -weight 1 grid columnconfigure $win 0 -weight 1 grid rowconfigure $win 0 -weight 1 $self configurelist $args } delegate method * to lframe delegate option * to lframe method CFG-LabelText {option value} { set options($option) $value $self UpdateLabel } method CFG-ChangeState {option value} { $self toggle set options($option) $value } method UpdateLabel {} { set sym [expr {$options(-state) eq "open" ? $open_symbol : $closed_symbol }] set text "$sym $options(-text)" } method getframe {} { # get the child site frame return $frame } method open {} { $self CFG-ChangeState -state open } method close {} { $self CFG-ChangeState -state closed } method isfloating {} { expr {$frame eq [winfo toplevel $frame]} } method toggle {} { # # Open or Close the frame # if {$options(-state) eq "open"} { # # grid remove remembers the slaves grid options :) # grid remove $frame # # Collapse the labelframe allowing a ltiile space for the # label # set lh [winfo height $label] $lframe configure -height [expr {$lh + 2}] set options(-state) closed } else { # # Don't bother if the frame has been floated into a toplevel # if {![$self isfloating]} { grid $frame set options(-state) open } } $self UpdateLabel } method float {} { # # Float the embedded frame as a toplevel # or reparent back into its container # # # Check if frame is masquerading as a Toplevel # (wm manage'd frames keep their names # if { ![$self isfloating] } { # # Not currently a toplevel, remem # # I'm not sure whether wm manage does a 'remove' or a 'forget' # so I note the current grid options for the frame # set ginfo [grid info $frame] # # Remove from paned window and then get Window Manager # to manage the frame # wm manage $frame wm title $frame $options(-floattitle) # # Make it the same size as the labelframe # set height [winfo height $lframe] set width [winfo width $lframe] wm geometry $frame ${width}x${height} # # Capture close event on new Toplevel and reparent # wm protocol $frame WM_DELETE_WINDOW [mymethod float] # # Collapse the labelframe to recover the space vertical # $self close } else { # # Reparent # wm forget $frame # # Open the containing labelframe # and manage using the saved settings # $self open grid $frame {*}$ginfo } } } if {0} { catch {destroy .clf} set clf [CollapsibleLabelFrame .clf \ -text "Click Me" \ -labelfg blue \ -floattitle "Whoo Hoo" \ ] pack $clf -fill both -expand 0 set f [$clf getframe] set b [ttk::button $f.b -text "Float Me" -command [list $clf float]] pack $b } ====== <>Snit Widgets