Ttk

Ttk is the Tile extension integrated into Tk as approved in TIP #248 .

See Also

Changing Ttk Widget Colors
Examples of using Tile/Ttk Widgets ttk::style examples
python-ttk
a Python package for ttk themed widgets

Documentation

official reference: intro
official reference: style
official reference: widget
Styles And Themes , TkDocs
various tips, e.g., how to replace -relief with pressed and !pressed
A Tour of the Tile Internals , 2005-09

Description

Ttk widgets coexist peacefully with classic Tk widgets.

There is no special Ttk package in Tk. It is simply part of Tk 8.5a6+ and is not distributed as a separate binary library. For the most part, it uses the ttk:: namespace, sharing the tk:: namespace and global commands where appropriate. The classic Tk widgets will all be referenceable from the tk:: namespace, in addition to remaining as global commands (for 8.x at least).

JE: Also: it's worth considering removing some or all of tk/generic/tkStyle.c (TIP#48 support)

Widgets

ttk::button
ttk::checkbutton
ttk::combobox
ttk::entry
ttk::frame
ttk::label
ttk::labelframe
ttk::menubutton
ttk::notebook
ttk::panedwindow
ttk::progressbar
ttk::radiobutton
ttk::scale
ttk::scrollbar
ttk::separator
ttk::sizegrip
ttk::spinbox
ttk::treeview

Styles

Elements

ttk_image
ttk_vsapi

Themes

ttk::theme::alt
ttk::theme::clam
ttk::theme::classic
ttk::theme::default
various ttk themes
black ttk theme
waldorf ttk theme
ttk::setTheme

Custom Background Color

2011-03-04: Wojciech Kocjan made a reply on clt about custom background color.

A few things I consider as design flaws in ttk tiles , clt, 2011-03-03

HaO reposted it here:

> 1) background color
> Why do some themes don't allow to change the background color. My
> application uses three different backgrounds depending on state:
> warning, error, active. Consider 'warning' when the entered value is
> near some limit, error if its out of limit, active if its currently
> processed.
> I considers this flaw as a no-go.

Yes and no. I agree it is silly you can't just specify background,
especially if you'd use "background" element.
I think it's OSX's theme's fault since you can do that on any platform
except for OSX. I remember seeing some

However, you can easily work around this - I needed a white frame/
label/checkbutton and native frame/label/checkbutton. So, I created
this:
image create photo image_osxWhite -width 16 -height 16
image_osxWhite put \#ffffff -to 0 0 16 16

ttk::style element create OSXWhiteBackground image image_osxBlank16 \
    -border {6 6 6 6} -padding {0} -sticky news
# (although I don't think -border is needed, not sure)

ttk::style layout OSXWhiteFrame {
    OSXWhiteWidget.background

}

ttk::style layout OSXWhiteLabel {
    OSXWhiteWidget.background -children {
        OSXWhiteLabel.label
    }

}
Again, I do agree here that if someone sets -background, it should be
doable.

But I found ttk layouts VERY useful - for example if you want to just
grab the highlighted frame OSX gives you, you can do:
ttk::style layout OSXHighlightedFrame {
    Entry.field

}

bind OSXHighlightedFrame <FocusIn> {%W state focus}
bind OSXHighlightedFrame <FocusOut> {%W state !focus}
And then for the widget:
$path configure -style OSXHighlightedFrame -padding {4 4}
bindtags $path [linsert [bindtags $path] 0 OSXHighlightedFrame]
I create an empty frame for non-OSX, a highlighted frame for OSX and
you can just put widgets in there (like text that doesn't have native
frames) - and they get OSX native frame for free :-)

So, while this particular thing is missing, ttk gives you enough tools
to work around it.

I think the worse thing is lack of introspection - if you want to
"mimic" ttk::checkbutton's default layout, you need to look in OSX
source code and TTK_BEGIN_LAYOUT to get the thing done right.
But, again, I think the advantages overwhelm the problems you can find
with ttk - if you fight such things, my recommendation is to learn ttk
elements, layouts etc.

Controllable Background in xp Theme

HaO 2011-03-18: Pat Thoyts on clt how to get a ttk entry with controllable background in xp theme Trouble changing background of ttk::entry widget , comp.lang.tcl, 2011-03-16:

>Does the vista theme, support changing the background color?
>I'm asking because i'm using this piece of code
>ttk::style map TEntry -fieldbackground list focus yellow
>which doesn't seem to be working.

The XP theme field element is drawn by the native XP themeing engine so
you don't get to pick and choose - the user gets what she expects from
the theme she has chosen for Windows (be it blue, green, silver or Zune)

To override this you need to replace the field element with one that you
can control more directly. You can do this by cloning the corresponding
element from one of the other themes (default will work) and configuring
it appropriately. The downside in this case is that the field is
handling the border style for the entry widget so you will get control
of the background but you loose control of the border. Maybe you can
work around that -- you can use the vsapi engine to create any XP
theming element you want and try to wrap that around the new background.

Anyway - an example:
# Sample of an overridden Entry widget which has an alternative
# background element that may be set to a given colour.
# Note that the colour is part of the style - not part of the widget data
# so all Plain.Entry widgets will use the same background colours.
#

package require Tk 8.5

proc PlainEntryInit {} {
    catch {
        # Import the 'default' theme field element.
        ttk::style element create plain.field from default
    }

    # Create a new style using the imported element.
    ttk::style layout Plain.Entry {
        Plain.Entry.plain.field -sticky nswe -border 1 -children {
             Plain.Entry.padding -sticky nswe -children {
                 Plain.Entry.textarea -sticky nswe
             }
         }
     }

     # Configure the colour and padding for our new style.
     ttk::style configure Plain.Entry {*}[ttk::style configure TEntry] \
         -fieldbackground LightSteelBlue -cursor hand2
     ttk::style map Plain.Entry {*}[ttk::style map TEntry] \
         -fieldbackground {!focus SteelBlue}

     # Re-do if the user changes theme.
     if {[lsearch -exact [bind . <<ThemeChanged>>] PlainEntryInit] == -1} {
         bind . <<ThemeChanged>> +PlainEntryInit
     }
  }

# Create a dialog to demonstrate the plain entry widget style
proc Test {dlg} {
    variable e "Plain.Entry widget"
    variable e2 "normal widget"
    wm title $dlg "Plain entry test"
    ttk::entry $dlg.e -style Plain.Entry -textvariable ::e
    ttk::entry $dlg.e2 -textvariable ::e2
    grid $dlg.e -pady 2 -padx 2
    grid $dlg.e2 -pady 2 -padx 2
    bind $dlg <Control-F2> {console show}
    return $dlg
}

if {!$tcl_interactive} {
    PlainEntryInit
    if {![winfo exists .plainentry]} {
        wm withdraw .
        set dlg [Test [toplevel .plainentry -class Dialog]]
        tkwait window $dlg
        exit
    }
}

Ttk Frame Around a Tk Widget

2011-03-14: Emiliano posted this code on clt to have a Ttk frame around a Tk widget

HaO: multi line ttk::entry , clt, 2011-03-09:

This is the code I've been using to wrap Tk widgets inside a Ttk border.

package require Tcl 8.5
package require Tk

namespace eval ::ttk {
    bind Wrapframe <FocusIn>  {%W#border state  focus}
    bind Wrapframe <FocusOut> {%W#border state !focus}
}

# wraps a plain Tk widget inside a ttk frame
proc ::ttk::WrapWidget {class path args} {
    # handle the args
    set args [dict replace $args \
        -background white \
        -borderwidth 0 \
        -highlightthickness 0]
    set args [dict remove $args -bg -bd]

    # real widget
    set rw $path.$class

    # create the container frame and the widget
    frame $path -style TEntry -class Wrapframe
    ::$class $rw {*}$args
    bindtags $rw [list $path $rw [string totitle $class] [winfo toplevel $path] all]

    # rename the container widget cmd and install
    # a proxy cmd to the real one
    rename ::$path ::${path}#border
    interp alias {} $path {} ::ttk::WrapProxy $rw

    pack $rw -expand 1 -fill both -padx 2 -pady 2

    # adjust the select{fore|back}ground with the theme
    bind $rw <<ThemeChanged>> [list apply {rw {
        set sb [ttk::style configure . -selectbackground]
        set sf [ttk::style configure . -selectforeground]
        $rw configure -selectbackground $sb
        $rw configure -selectforeground $sf
    }} $rw]
    after idle [list after 0 [list \
        event generate $rw <<ThemeChanged>>]]

    return $path

}

proc ::ttk::WrapProxy {w args} {
    # prevent the border window to take focus
    if {[lindex $args 0] eq "cget" &&
        [lindex $args 1] eq "-takefocus"} {
        return 0
    }
    uplevel 1 [linsert $args 0 $w]

}

interp alias {} ::ttk::text    {} ::ttk::WrapWidget text
interp alias {} ::ttk::listbox {} ::ttk::WrapWidget listbox
interp alias {} ::ttk::canvas  {} ::ttk::WrapWidget canvas

# demo
pack [ttk::text .t -width 20 -height 4] -padx 6 -pady 6
pack [ttk::entry .e -width 20] -padx 6 -pady 6
after 2000 {ttk::setTheme clam}

Custom Widget Creation

HaO 2011-03-13: Pat Thoyts on the core list about Ttk widget creation. For me, this was very valuable so I have put it here. Feel free to delete, format or move to another place.

One of the original intents of 'tile' was to make it simpler to create
Tk widgets. There's quite a lot of tedious boilerplate in Tk widget
creation. See http://tktable.sourceforge.net/tile/WidgetGuide.html  for
something about this. However, when 'tile' got integrated the necessary
functions were not exposed as part of the tk stubs and its currently
somewhat hidden.

Related to this -- to construct new UI's using elements you need a
reasonably general purpose element engine. I one toyed with using GDI+
so I could specify an element with, for instance, a certain gradient or
shape. Working with this leads to the obvious conclusion that it would
be great to be able to specify the look of an element using something
like SVG. (See http://tktable.sourceforge.net/tile/Gdiplus.html 
and http://www.patthoyts.tk/gitweb.cgi?p=gdiplus;a=summary )

There might be more involved in making the widget functionality easy to
hook together but this would cover the look part of look and
feel. Events mostly deal with 'feel'.

Questions

LV 2007-Nov-01:

Bottom line question - if someone wants (or needs) to use a ttk widget, what do they need to do to begin? Would someone who is familar with ttk be willing to write a step by step example of moving a relatively simple application from being an original Tk widget application to an application using Tk and Ttk?

History

 0.7.8 tile source base       => Tk source base integration (completed 2006-10-30)

 tile:                        => tk
  aclocal.m4                  => ''n/a''
  ChangeLog                   => ''n/a''
  configure*                  => ''n/a''
  configure.in                => ''n/a''
  demos/                      => library/demos/... (''partial'')
  doc/                        => doc/ttk_*
  generic/                    => generic/ttk/...
  library/                    => library/ttk/...
  license.terms               => ''n/a''
  macosx/                     => macosx/...
  Makefile.in                 => ''n/a''
  README.txt                  => ''n/a''
  tclconfig/                  => ''n/a''
  tests/                      => tests/ttk/...
  tools/                      => ''n/a''
  win/                        => win/...

 tile/demos:                  => tk/library/demos/...
  autocomplete.tcl            => ''n/a''
  demo.tcl                    => ttk_demo.tcl
  dirbrowser.tcl              => ''n/a''
  dlgtest.tcl                 => ''n/a''
  iconlib.tcl                 => ttk_iconlib.tcl
  repeater.tcl                => ttk_repeater.tcl
  themes/                     => ''n/a''
  toolbutton.tcl              => ''n/a''

 tile/demos/themes:           => ''n/a''

 tile/doc:                    => tk/doc/...
  Doc files translated to ttk_* with a few exceptions:
  converting.txt              => ''n/a''
  Makefile                    => ''n/a''
  man.macros                  => ''n/a''
  paned.n                     => ttk_panedwindow.n
  tile-intro.n                => ttk_intro.n
  TILE.XML                    => ''n/a''
  tmml.options                => ''n/a''

 tile/generic:                => tk/generic/ttk/...
  altTheme.c                  => ttkDefaultTheme.c
  blink.c                     => ttkBlink.c
  button.c                    => ttkButton.c
  cache.c                     => ttkCache.c
  clamTheme.c                 => ttkClamTheme.c
  classicTheme.c              => ttkClassicTheme.c
  configure*                  => ''n/a''
  configure.in                => ''n/a''
  entry.c                     => ttkEntry.c
  frame.c                     => ttkFrame.c
  gunk.h                      => ''n/a''
  image.c                     => ttkImage.c
  label.c                     => ttkLabel.c
  layout.c                    => ttkLayout.c
  Makefile.in                 => ''n/a''
  manager.c                   => ttkManager.c
  manager.h                   => ttkManager.h
  notebook.c                  => ttkNotebook.c
  paned.c                     => ttkPanedwindow.c
  pkgIndex.tcl.in             => ''n/a''
  progress.c                  => ttkProgress.c
  scale.c                     => ttkScale.c
  scrollbar.c                 => ttkScrollbar.c
  scroll.c                    => ttkScroll.c
  separator.c                 => ttkSeparator.c
  square.c                    => ttkSquare.c
  stepTheme.c                 => ''n/a''
  tile.c                      => ttkInit.c
  tkElements.c                => ttkElements.c
  tkstate.c                   => ttkState.c
  tkTheme.c                   => ttkTheme.c
  tkTheme.h                   => ttkTheme.h
  tkThemeInt.h                => ttkThemeInt.h
  TODO                        => ''n/a''
  trace.c                     => ttkTrace.c
  track.c                     => ttkTrack.c
  treeview.c                  => ttkTreeview.c
  ttk.decls                   => ttk.decls
  ttkDecls.h                  => ttkDecls.h
  ttkStubInit.c               => ttkStubInit.c
  ttkStubLib.c                => ttkStubLib.c
  widget.c                    => ttkWidget.c
  widget.h                    => ttkWidget.h

 tile/library:                => tk/library/ttk/...
  File names remained the same with these exceptions:
  paned.tcl                   => panedwindow.tcl
  stepTheme.tcl               => ''n/a''
  tile.tcl                    => ttk.tcl

 tile/macosx:                 => tk/macosx/...
  aquaTheme.c                 => ttkMacOSXTheme.c

 tile/tclconfig:              => ''n/a''

JE The *.tcl files in tile/tests (except for all.tcl) are mostly small interactive tests that I used during development. There's no real need to import them into the Tk CVS repository.

 tile/tests:                  => tk/tests/ttk/...
  The *.tcl files were removed, other files were moved to the above directory

 tile/tools:                  => tk/tools
  genStubs.tcl                => ''n/a'' Not included yet, needed for Ttk stubs library

 tile/win:                    => tk/win
  makefile.vc                 => ''n/a''
  monitor.c                   => ttkWinMonitor.c
  nmakehlp.c                  => ''n/a''
  rules.vc                    => ''n/a''
  Tile.dsp                    => ''n/a''
  winTheme.c                  => ttkWinTheme.c
  xpTheme.c                   => ttkWinXPTheme.c

KJN: Is it intended to supply any demos with Tk 8.5? I'm looking for the demos in 8.5b1, and I can't find them in the locations mentioned above:

 tile/demos:                  => tk/library/demos/...
  demo.tcl                    => ttk_demo.tcl
  iconlib.tcl                 => ttk_iconlib.tcl
  repeater.tcl                => ttk_repeater.tcl

JH: The tile demo was designed more as a comparison view for core developers to understand theming. What we need in 8.5 is straight new demos that update the regular demos with fully themed widgets. This is something that we really need to work on for 8.5.0 (and ongoing).