# Tcl/Tk 中的布局管理

> 原文： [http://zetcode.com/gui/tcltktutorial/layout/](http://zetcode.com/gui/tcltktutorial/layout/)

在 Tcl/Tk 编程教程的这一部分中，我们将介绍布局管理器。

在设计应用的 GUI 时，我们决定要使用哪些小部件以及如何在应用中组织这些小部件。 为了组织小部件，我们使用专门的不可见对象，称为布局管理器。

有两种小部件：容器及其子级。 容器将子项分组为合适的布局。

Tk 具有三个内置布局管理器：`pack`，`grid`和`place`管理器。 包几何形状管理器在垂直和水平框中组织小部件。 网格几何管理器将小部件放置在二维网格中。 最后，`place`几何管理器使用绝对定位将小部件放置在其容器上。

## 绝对定位

在大多数情况下，程序员应使用布局管理器。 在某些情况下，我们可以使用绝对定位。 在绝对定位中，程序员以像素为单位指定每个小部件的位置和大小。 如果我们调整窗口大小，则小部件的大小和位置不会改变。 在各种平台上，应用看起来都不同，在 Linux 上看起来不错，在 Mac OS 上看起来不太正常。 在我们的应用中更改字体可能会破坏布局。 如果我们将应用翻译成另一种语言，则必须重做您的布局。

```tcl
#!/usr/bin/wish

# ZetCode Tcl/Tk tutorial
#
# In this script, we lay out images
# using absolute positioning.
#
# author: Jan Bodnar
# last modified: March 2011
# website: www.zetcode.com

package require Img

frame .fr -background "#333"
pack .fr -fill both -expand 1

image create photo img1 -file "bardejov.jpg"
label .fr.lbl1 -image img1
place .fr.lbl1 -x 20 -y 20

image create photo img2 -file "rotunda.jpg"
label .fr.lbl2 -image img2
place .fr.lbl2 -x 40 -y 160

image create photo img3 -file "mincol.jpg"
label .fr.lbl3 -image img3
place .fr.lbl3 -x 170 -y 50

wm title . "absolute" 
wm geometry . 300x280+300+300

```

在此示例中，我们使用绝对定位放置了三个图像。 我们将使用位置几何图形管理器。

```tcl
package require Img

```

我们使用`Img`包来显示 JPG 图像。 在 Ubuntu Linux 上，我们必须安装`libtk-img`包。

```tcl
package require Img

```

要显示 JPG 图像，我们使用`Img`包。

```tcl
frame .fr -background "#333"

```

我们的框架将具有深灰色背景。

```tcl
image create photo img1 -file "bardejov.jpg"

```

我们从当前工作目录中的图像创建照片图像对象。

```tcl
label .fr.lbl1 -image img1

```

我们用图像创建一个`label`。 标签可以包含文本或图像。

```tcl
place .fr.lbl1 -x 20 -y 20

```

标签放置在框架上的`x = 20`，`y = 20`坐标处。 绝对定位通过`place`命令完成。

![Absolute positioning](img/f2e6eb26b9d488c841afe0f06ca2126b.jpg)

图：绝对定位

## 按钮示例

在下面的示例中，我们将在窗口的右下角放置两个按钮。 我们将使用`pack`管理器。

```tcl
#!/usr/bin/wish

# ZetCode Tcl/Tk tutorial
#
# In this script, we use pack manager
# to position two buttons in the
# bottom right corner of the window.
#
# author: Jan Bodnar
# last modified: March 2011
# website: www.zetcode.com

frame .fr
pack .fr -fill both -expand 1

frame .fr.pnl -relief raised -borderwidth 1
pack .fr.pnl -fill both -expand 1

ttk::button .fr.cb -text "Close"
pack .fr.cb -padx 5 -pady 5 -side right
ttk::button .fr.ok -text "OK"
pack .fr.ok -side right

wm title . "buttons" 
wm geometry . 300x200+300+300

```

我们将有两个框架。 有一个基础框架和一个附加框架，该框架将在两个方向上扩展并将两个按钮按到基础框架的底部。 这些按钮放置在水平框中，并位于此框的右侧。

```tcl
frame .fr.pnl -relief raised -borderwidth 1
pack .fr.pnl -fill both -expand 1

```

我们创建另一个`frame`小部件。 该小部件占用了大部分区域。 我们更改框架的边框，以使框架可见。 默认情况下，它是平坦的。 `pack`管理器在两个方向上扩展框架。 水平和垂直。

```tcl
ttk::button .fr.cb -text "Close"
pack .fr.cb -padx 5 -pady 5 -side right

```

创建一个关闭按钮。 将其放入水平盒中。 `-side`选项将创建一个水平框布局，其中按钮位于框的右侧。 `-padx`和`-pady`选项将在小部件之间放置一些空间。 `-padx`在按钮小部件之间以及关闭按钮和根窗口的右边框之间放置一些空间。 `-pady`在按钮小部件与框架和根窗口的边框之间放置一些空间。

```tcl
pack .fr.ok -side right

```

`ok`按钮位于关闭按钮旁边。 它们之间有 5px 的间距。

![Buttons example](img/6717336bcf4ea469491868d7ed6e287a.jpg)

图：按钮示例

## 计算器

我们将使用 Tk 网格几何管理器来创建计算器的骨架。

```tcl
#!/usr/bin/wish

# ZetCode Tcl/Tk tutorial
#
# In this script, we use the grid manager
# to create a skeleton of a calculator.
#
# author: Jan Bodnar
# last modified: March 2011
# website: www.zetcode.com

frame .fr -padx 5 -pady 5
pack .fr -fill both -expand 1

ttk::style configure TButton -width 8 -height 8 -font "serif 10" 

entry .fr.ent 
grid .fr.ent -row 0 -columnspan 4 -sticky we

ttk::button .fr.cls -text "Cls" 
grid .fr.cls -row 1 -column 0
ttk::button .fr.bck -text "Back"
grid .fr.bck -row 1 -column 1
ttk::button .fr.lbl
grid .fr.lbl -row 1 -column 2   
ttk::button .fr.clo -text "Close"
grid .fr.clo -row 1 -column 3
ttk::button .fr.sev -text "7"
grid .fr.sev -row 2 -column 0  
ttk::button .fr.eig -text "8"
grid .fr.eig -row 2 -column 1         
ttk::button .fr.nin -text "9"
grid .fr.nin -row 2  -column 2
ttk::button .fr.div -text "/"
grid .fr.div -row 2 -column 3

ttk::button .fr.fou -text "4"
grid .fr.fou -row 3 -column 0
ttk::button .fr.fiv -text "5"
grid .fr.fiv -row 3 -column 1
ttk::button .fr.six -text "6"
grid .fr.six -row 3 -column 2 
ttk::button .fr.mul -text "*"
grid .fr.mul -row 3 -column 3    

ttk::button .fr.one -text "1"
grid .fr.one -row 4 -column 0
ttk::button .fr.two -text "2"
grid .fr.two -row 4 -column 1
ttk::button .fr.thr -text "3"
grid .fr.thr -row 4 -column 2
ttk::button .fr.mns -text "-"
grid .fr.mns -row 4 -column 3

ttk::button .fr.zer -text "0"
grid .fr.zer -row 5 -column 0
ttk::button .fr.dot -text "."
grid .fr.dot -row 5 -column 1         
ttk::button .fr.equ -text "="
grid .fr.equ -row 5 -column 2
ttk::button .fr.pls -text "+"
grid .fr.pls -row 5 -column 3

grid columnconfigure .fr 0 -pad 3
grid columnconfigure .fr 1 -pad 3
grid columnconfigure .fr 2 -pad 3
grid columnconfigure .fr 3 -pad 3

grid rowconfigure .fr 0 -pad 3        
grid rowconfigure .fr 1 -pad 3  
grid rowconfigure .fr 2 -pad 3  
grid rowconfigure .fr 3 -pad 3  
grid rowconfigure .fr 4 -pad 3  

wm title . "calculator" 
wm geometry . +300+300

```

在此示例中，我们使用`grid`管理器来组织框架容器小部件中的按钮。

```tcl
ttk::style configure TButton -width 8 -height 8 -font "serif 10" 

```

我们将主题`button`小部件配置为具有特定字体并具有一些内部填充。

```tcl
entry .fr.ent 
grid .fr.ent -row 0 -columnspan 4 -sticky we

```

`entry`小部件是显示数字的地方。 小部件位于第一行，它将覆盖所有四列。 小部件可能不会占用网格中单元所分配的所有空间。 `-sticky`选项将沿给定方向扩展小部件。 在我们的案例中，我们确保条目小部件从左向右展开。

```tcl
ttk::button .fr.cls -text "Cls" 

```

`cls`按钮位于第二行和第一列。 请注意，行和列从零开始。 `ttk::button`是一个主题按钮。

```tcl
grid columnconfigure .fr 0 -pad 3
...
grid rowconfigure .fr 0 -pad 3  

```

我们使用`columnconfigure`和`rowconfigure`命令在网格列和行中定义一些空间。 这样，我们可以实现按钮之间有一定的间隔。

![Calculator](img/c4de7f838b0aa3a11e3293eb8b6a8741.jpg)

图：计算器

## Windows 示例

以下示例使用网格几何管理器创建 Windows 对话框。 该对话框来自 JDeveloper 应用。

```tcl
#!/usr/bin/wish

# ZetCode Tcl/Tk tutorial
#
# In this script, we use the grid
# manager to create a more complicated
# layout.
#
# author: Jan Bodnar
# last modified: March 2011
# website: www.zetcode.com

frame .fr -padx 5 -pady 5
pack .fr -fill both -expand 1

label .fr.lbl -text Windows
grid .fr.lbl -sticky w -pady 4 -padx 5

text .fr.area
grid .fr.area -row 1 -column 0 -columnspan 2 \
    -rowspan 4 -padx 5 -sticky ewsn 

ttk::button .fr.act -text Activate
grid .fr.act -row 1 -column 3

ttk::button .fr.cls -text Close
grid .fr.cls -row 2 -column 3 -pady 4

ttk::button .fr.hlp -text Help
grid .fr.hlp -row 5 -column 0 -padx 5

ttk::button .fr.ok -text OK
grid .fr.ok -row 5 -column 3

grid columnconfigure .fr 1 -weight 1
grid columnconfigure .fr 3 -pad 7

grid rowconfigure .fr 3 -weight 1
grid rowconfigure .fr 5 -pad 7

wm title . "Windows" 
wm geometry . 350x300+300+300

```

在此示例中，我们将使用`label`小部件，`text`小部件和四个按钮。

```tcl
label .fr.lbl -text Windows
grid .fr.lbl -sticky w -pady 4 -padx 5

```

标签窗口小部件已创建并放入网格中。 如果未指定列和行，则假定为第一列或行。 该标签向西粘贴，并且其文本周围有一些填充。

```tcl
text .fr.area
grid .fr.area -row 1 -column 0 -columnspan 2 \
    -rowspan 4 -padx 5 -sticky ewsn 

```

`text`小部件已创建，并从第二行第一列开始。 它跨越`2`列和`4`行。 小部件和根窗口的左边界之间有 4px 空间。 最后，它坚持所有四个方面。 因此，调整窗口大小时，`text`小部件会向各个方向扩展。

```tcl
grid columnconfigure .fr 1 -weight 1
grid columnconfigure .fr 3 -pad 7

grid rowconfigure .fr 3 -weight 1
grid rowconfigure .fr 5 -pad 7

```

我们在网格中的小部件之间定义一些空间。 在`text`小部件和按钮之间放置最大的空间。

![Windows example](img/ea4e7e3b76e782fe49bc4f7921b81787.jpg)

图：窗口示例

在 Tcl/Tk 教程的这一部分中，我们提到了小部件的布局管理。