Laying Out Widgets With The grid Command

Short Examples

The grid command allows you to lay out items in a grid, sort of like an HTML table, where the columns and rows line up.


The main use of the grid command is to control the layout of data-entry forms. Such forms are the hardest things to get to properly line up if you use the pack command.

What follows are two short examples using the grid command: a main window and a data-entry form.

Main Window

The following short example shows the grid command in operation to create an application main window.

The standard application main window, on Unix or Windows, sports a menubar at the top. Immediately beneath the menubar you can have a toolbar. Beneath that lies the main application area. This is where your documents would go and so on. Finally, at the bottom of the window lies a message or status area, used to present short one-line help messages and general status information to the user.

When such a main window gets resized, the extra vertical space should go to the main application area. Extra horizontal space should go to all these areas, as each spans the entire main window.

In Tcl terms, each area is a frame widget. With the grid command, we place each frame in "column" 0. Each frame spans one column. When we configure the grid, we need to ensure that the column can be resized.

Since we're essentially lining things up vertically, each frame widget gets placed in its own row, starting with row 0. Because only the main application area needs to grow vertically, we should configure the grid for that row to expand.

To do this, we give row 2 (where the main area resides) a resize "weight" of 1. The other rows default to a weight of 0. Any extra space is divided based on the relative weights of the rows. Since row 2 is the only row with a weight, it gets all the space.

The code to do this follows:

grid rowconfigure . 2 -weight 1

You need to configure column 0, the only column, similarly to allow it to grow:

grid columnconfigure . 0 -weight 1

Finally, to allow resizing, we make each widget "sticky" in its grid cell against all four edges (n, s, e and w). This means that as the cell grows, the widget will also grow.

What follows is an example Tcl file using the grid command. I've simplified the example, so that there is only one menu and a simple toolbar button. Try it out and resize the window. It should resize properly. Note that you'll need the beta 1 or higher versions of Tcl 7.5 and Tk 4.1 for this to work.

If everything works, you should see a window like the following:

screen view of gridtest.tcl showing file bar, edit button, main application area, and status area

# gridtest.tcl
# This test shows how to make a standard
# main window with a menubar, toolbar,
# main area and status area at the bottom and
# have the window properly resize.
# 8-Feb-96
# Copyright 1996 Eric Foster-Johnson

# Menubar
frame .menubar -bd 2 -relief raised

menubutton .menubar.file -underline 0 -text "File" -menu
menu add command -label "Exit" -underline 1 -command { exit }

# Mix old pack with new grid
pack .menubar.file -side left

# Toolbar
frame .toolbar -bd 2 -relief groove
button .toolbar.edit -text "Edit"
pack .toolbar.edit -side left

# Main Area
frame .main -bd 2 -relief groove
label .main.label -text "Main Application Area"
pack .main.label -padx 100 -pady 50 

# Status Area
frame .status -bd 1 -relief flat
label .status.msg -relief sunken -bd 2 -text "Status Area"
label -relief sunken -bd 2 -text "WunderWord 1.0"
pack  .status.msg -side left -expand true -fill x
pack -side right

# Test grid layout. All widgets are in the same column; and each
# take up one row.
# Each widget is sticky to all four edges so that it expands to fit.
grid config .menubar -column 0 -row 0 \
-columnspan 1 -rowspan 1 -sticky "snew" 
grid config .toolbar -column 0 -row 1 \
-columnspan 1 -rowspan 1 -sticky "snew" 
grid config .main    -column 0 -row 2 \
-columnspan 1 -rowspan 1 -sticky "snew" 
grid config .status  -column 0 -row 3 \
-columnspan 1 -rowspan 1 -sticky "snew" 

# Set up grid for resizing.
# Column 0 (the only one) gets the extra space.
grid columnconfigure . 0 -weight 1

# Row 2 (the main area) gets the extra space.
grid rowconfigure . 2 -weight 1

Data Entry Form

The data-entry form style of layout works very well with the grid command, since placing widgets into columns and rows is exactly what you want to do for data-entry forms.

Typically, you'll use label and entry widgets throughout the form. The entry widgets accept the data, the label widgets explain the purpose of the entry.

The problem with most layouts is that you often need differing text lengths and differing entry widths. Together, this means that nice rows and columns get messed up.

With the grid layout, though, you simply place widgets into columns and rows and the grid layout manager ensures that the columns and rows line up.

The short example below shows four columns of widgets: labels, entries, labels and entries, for a a hypothetical computer user database. When you run the code below, you'll see a window a lot like the following:

screen view of grid2.tcl showing two columns of fields, including full name, title, address, office phone number, fax, user name, home system name, email, and URL

Note how even though some labels have more text than others, everything still lines up. Also, to make all the labels aligned to the right side, I used only "East" (or e) stickiness in the grid configurations for the label widgets.

# grid2.tcl
# Test of new grid packing command.
# This test shows how to make a data entry form.
# 21-Feb-96
# Copyright 1996 Eric Foster-Johnson

# In this example, we have two columns of data entry
# fields. Under the hood, we use four columns because
# the labels take up one column and the data-entry
# fields take up another column.

# Labels for the data entry fields.
# Note that a few of the labels use a lot of text to
# show the effects of the grid layout.
label .l_name  -text "Full name: "
label .l_titlw -text "Title: "
label .l_addr  -text "Address: "
label .l_offph -text "Office phone number: "
label .l_faxph -text "Fax: "

label .l_user  -text "User name: "
label .l_homesys -text "Home system name: "
label .l_email -text "Email: "
label .l_url   -text "URL: " 

# Data-entry fields. Note the different lengths to
# show the effect of the grid.

entry .e_name   -width 20
entry .e_titlw  -width 10
entry .e_addr   -width 20
entry .e_offph  -width 10
entry .e_faxph  -width 10

entry .e_user    -width 12
entry .e_homesys -width 12
entry .e_email   -width 20
entry .e_url     -width 20

# Set up grid layout (instead of packing).
grid config .l_name   -column 0 -row 0 -sticky "e"
grid config .l_titlw  -column 0 -row 1 -sticky "e"
grid config .l_addr   -column 0 -row 2 -sticky "e"
grid config .l_offph  -column 0 -row 3 -sticky "e"
grid config .l_faxph  -column 0 -row 4 -sticky "e"

grid config .e_name   -column 1 -row 0 -sticky "snew"
grid config .e_titlw  -column 1 -row 1 -sticky "snew"
grid config .e_addr   -column 1 -row 2 -sticky "snew"
grid config .e_offph  -column 1 -row 3 -sticky "snew"
grid config .e_faxph  -column 1 -row 4 -sticky "snew"

grid config .l_user    -column 2 -row 0 -sticky "e"
grid config .l_homesys -column 2 -row 1 -sticky "e"
grid config .l_email   -column 2 -row 2 -sticky "e"
grid config .l_url     -column 2 -row 3 -sticky "e"

grid config .e_user    -column 3 -row 0 -sticky "snew"
grid config .e_homesys -column 3 -row 1 -sticky "snew"
grid config .e_email   -column 3 -row 2 -sticky "snew"
grid config .e_url     -column 3 -row 3 -sticky "snew"

# Set up grid for resizing.
grid columnconfigure . 1 -weight 1
grid columnconfigure . 3 -weight 1