Ttk's labelframe widget.

  Styling the labelframe

Bryan Oakley 28-Feb-2008 Since there's a dearth of information available about tweaking ttk::styles and themes, I thought I'd share this bit of code. I'm finding that path to ttk enlightenment is a bit rocky, but view at the end of the trail is pretty nice.

For my immediate needs I was wanting a labelframe that had a dark background, and instead of a border I wanted an underline under the label. Something like this:

  Common tasks
  * task one
  * task two
  * task three

The initial stumbling blocks were how to replace the border with a single line, and how to get the background of the label to change. The following code is what I came up with.

The solutions to the two stumbling blocks turned out to be pretty trivial. For the former I had to modify the layout of my frame to use a separator element rather than a border element. For the latter, the solution was to realize I had to configure the background of "custom.TLabelframe.Label" rather than just "custom.TLabelframe".

Here's the code, which should be full cut'n'pasteable:

  package require Tk
  font create underlineFont {*}[font actual TkDefaultFont] -underline true
  set background #0b223a
  set foreground white
  ttk::style configure custom.TLabelframe.Label \
    -background $background \
    -foreground $foreground
  ttk::style configure custom.TLabelframe \
    -background $background \
    -foreground $foreground \
    -labeloutside true \
    -labelmargins {0 0 0 4}
  ttk::style layout custom.TLabelframe {
    Separator.separator -sticky new
  ttk::style configure custom.TButton \
    -background $background \
    -foreground $foreground \
    -anchor w
  ttk::style map custom.TButton \
    -font {active underlineFont}
  ttk::style layout custom.TButton {
      border -children {
         padding -sticky nswe -border 1 -children {
             label -sticky nswe
  . configure -background $background
  ttk::labelframe .lf -style custom.TLabelframe -text "Common Tasks"
  # N.B. \u2022 is a unicode bullet
  ttk::button .lf.b1 -style custom.TButton -text "\u2022 task one"
  ttk::button .lf.b2 -style custom.TButton -text "\u2022 task two"
  ttk::button .lf.b3 -style custom.TButton -text "\u2022 task three"
  pack .lf.b1 .lf.b2 .lf.b3 -side top -fill x -anchor w
  pack .lf -side top -fill both -expand true -padx 4 -pady 4

  Labelframes that enable their contents

jnc Feb 15, 2010: labelframe has the cool option of -labelwidget. This enables common frames with a checkbox to enable/disable the frames contents. An example:

 package require Tk
 set ::enabled 0
 set ::name World
 ttk::labelframe .lf1
 ttk::checkbutton .lf1.cb1 -text "Say Hello To" -variable ::enabled -command {
         if {$::enabled} {
                 .lf1.e1 configure -state normal
                 .b1 configure -state normal
         } else {
                 .lf1.e1 configure -state disabled
                 .b1 configure -state disabled
 .lf1 configure -labelwidget .lf1.cb1
 ttk::entry .lf1.e1 -state disabled -textvariable ::name -state disabled
 pack .lf1.e1 -fill x
 ttk::button .b1 -text {Say Hello} -command { puts "Hello, $::name" } -state disabled
 ttk::button .b2 -text Exit -command exit
 pack .lf1 .b1 .b2 -fill x -expand yes
 focus -force .b1

Frame does not shrink to 0 height if last children is unpacked/ungridded

See the page frame for a descriptions and solutions.