Version 8 of writing readable, manageable, reusable Tk

Updated 2003-08-12 11:22:52

aricb Too often I find that when I write Tk code to do anything non-trivial, I end up with a sprawling disaster that is a pain to modify or even understand six months later. As I'm sure other programmers have encountered this problem, I searched for some guidelines on the Wiki and on the web. I'll share what I found below. However, I came to the conclusion that much more could (and should) be said on this topic.

Here's what I've found so far (please add to this list):

Tom Tromey's style guide [L1 ] has an excellent section on Tk. By contrast, Ray Johnson's Tcl style guide [L2 ], which has become the de facto standard for Tcl, doesn't address Tk specifically.

A handful of wiki pages address this topic:


Here's what little I currently do to make my code more readable. Please share any reactions to these:

  • In all but the most trivial scripts, I create new toplevels instead of using .
  • I try to combine geometry management with widget creation when possible, i.e.
 grid [text .mytoplevel.text] -row 0 -column 0

However, when I have to specify lots of options for the widget and/or the geometry manager, I end up with long lines which IMHO look bad even if I break them up with backslashes.

  • I try to break things up into small procs, where (for example) one proc will create a frame and its children and another proc will create bindings for those widgets.

PWQ 12 Aug 2003 I use a table driven approach to gui creation. As an example

 set widgetlist { {button $par.b -command xx} {entry $par.e -width 6}}
 foreach w $widgetlist {
   pack [eval $w] -anc nw
 }

(Peter Lewerin did minor edit to make it executable.)

The command as listed in the list (which can be spread out over multiple lines) become much easier to read.

I have a system that extends this concept but is to complex to outline here, here is an example screen as an example (Stored in a file/database etc is the gui definition ):

 Options {

        *LogoEntry*Entry*font {Times 24}
        *LogoPanel*Canvas*width 600
        *LogoPanel*Canvas*height 400
        *LogoMenu*Button*ipadx 0
        *LogoMenu*Button*padX 2
        *LogoMenu*Button*relief solid
 }

 Form Logo {
        Script { namespace eval Logo {set __create 1.0} }
 V3S#LogoPanel {
        H#LogoMenu {
          V3s {
           H3r {
                PackOptions {-anc w -padx 1}
                H1s {
                        PackOptions {-anc w -padx 1}
                        T { }
                        T {Test:}
                        B {{Clear} {::Logo::test:clear}  }
                        B {{Check} {::Logo::test:check}  }
                        B {{Load} {::Logo::test:load}  }
                        B {{Save} {::Logo::test:save}  }
                }
                 Sb/Lv {{{-orient v -command {!Logo yview}  -width 10 }}} {-fill 

y}

                Lb/Logo:Logo::data(_cmds) {-font {{{Times 18 bold}}} -width 0 {{
 -yscrollc {!Lv set}}} } {-fill y -expand 0}
                V+b {
                        E/Vars:Logo::data(_vars) {0} {-fill x}
                        H+b {
               T { }
                T {Programme: }
                B {{Save} {turtleSave [!Prog get 0 end] [!Vars get]} }
                B {{Load} {turtleLoad !Prog}}

      ........

Notes:

H means arrange horizontally

V means vertically.

The # defines the class.

The second item in each list are short cuts for the most common widget option.

Ie B {{Save} -justify c} equals button -text Save -justify c.

The third list item are the manager options (ie pack).

/xx associates a variable with the widget.

:xx defines a reference to the widget that can be used in other widget definitions

Names above are abbreviations (is B is button, Sb scrollbar, Lb listbox etc.


Please contribute any principles that help you write Tk code in a more readable, manageable, and/or reusable way.


Category Design | Category Concept | Category GUI