Tcl/Tk 中的布局管理
最后修改于 2023 年 10 月 18 日
在本 Tcl/Tk 编程教程中,我们将介绍布局管理器。
当我们设计应用程序的 GUI 时,我们决定使用哪些小部件以及如何在应用程序中组织这些小部件。为了组织我们的小部件,我们使用称为布局管理器的专用非可见对象。
有两种小部件:容器及其子项。容器将其子项分组到合适的布局中。
Tk 有三个内置的布局管理器:pack
、grid
和 place
管理器。pack 几何管理器以垂直和水平框的形式组织小部件。grid 几何管理器将小部件放置在二维网格中。最后,place
几何管理器使用绝对定位将小部件放置在其容器上。
绝对定位
在大多数情况下,程序员应该使用布局管理器。在少数情况下,我们可以使用绝对定位。在绝对定位中,程序员以像素为单位指定每个小部件的位置和大小。如果调整窗口大小,小部件的大小和位置不会改变。应用程序在各种平台上看起来有所不同,在 Linux 上看起来可以的,在 Mac OS 上可能看起来不好。更改应用程序中的字体可能会破坏布局。如果我们将应用程序翻译成另一种语言,我们必须重新进行布局。
#!/usr/bin/wish # ZetCode Tcl/Tk tutorial # # In this script, we lay out images # using absolute positioning. # # Author: Jan Bodnar # 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
在此示例中,我们使用绝对定位放置三个图像。我们使用 place 几何管理器。
package require Img
我们使用 Img
包来显示 JPG 图像。
$ sudo apt install libtk-img
在 Linux 上,我们必须安装 libtk-img
包。
package require Img
要显示 JPG 图像,我们使用 Img
包。
frame .fr -background "#333"
我们的 frame 将有一个深灰色的背景。
image create photo img1 -file "bardejov.jpg"
我们从当前工作目录中的图像创建一个 photo image 对象。
label .fr.lbl1 -image img1
我们创建一个带有图像的 label
。标签可以包含文本或图像。
place .fr.lbl1 -x 20 -y 20
标签放置在 frame 上,坐标为 x=20, y=20。绝对定位使用 place
命令完成。

按钮示例
在下面的示例中,我们将两个按钮放置在窗口的右下角。我们使用 pack
管理器。
#!/usr/bin/wish # ZetCode Tcl/Tk tutorial # # In this script, we use the pack # manager to place two buttons in # bottom-right corner of the window # # Author: Jan Bodnar # 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 . 350x300+300+300
我们有两个 frame。有一个基本 frame 和一个附加 frame,它将在两个方向上展开,并将两个按钮推到基本 frame 的底部。按钮放置在一个水平框中,并放置在该框的右侧。
frame .fr.pnl -relief raised -borderwidth 1 pack .fr.pnl -fill both -expand 1
我们创建另一个 frame
小部件。此小部件占据大部分区域。我们更改 frame 的边框,以便 frame 可见。默认情况下它是平的。pack
管理器在两个方向上展开 frame。水平和垂直。
ttk::button .fr.cb -text "Close" pack .fr.cb -padx 5 -pady 5 -side right
创建关闭按钮。它被放入一个水平框中。-side
选项将创建一个水平框布局,其中按钮放置在框的右侧。-padx
和 -pady
选项将在小部件之间留出一些空间。-padx
在按钮小部件之间以及在关闭按钮和根窗口的右边框之间留出一些空间。-pady
在按钮小部件之间以及在 frame 和根窗口的边框之间留出一些空间。
pack .fr.ok -side right
ok
按钮放置在关闭按钮旁边。它们之间有 5px 的空间。

计算器
我们使用 Tk grid 几何管理器创建一个计算器的骨架。
#!/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 # 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
管理器在 frame 容器小部件中组织按钮。
ttk::style configure TButton -width 8 -height 8 -font "serif 10"
我们配置主题 button
小部件以具有特定的字体并具有一些内部填充。
entry .fr.ent grid .fr.ent -row 0 -columnspan 4 -sticky we
entry
小部件是显示数字的地方。小部件放置在第一行,并将跨越所有四列。小部件可能不会占用网格中单元格分配的所有空间。-sticky
选项将在给定方向上展开小部件。在我们的例子中,我们确保 entry 小部件从左到右展开。
ttk::button .fr.cls -text "Cls"
cls 按钮放置在第二行和第一列。请注意,行和列从零开始。ttk::button
是一个主题按钮。
grid columnconfigure .fr 0 -pad 3 ... grid rowconfigure .fr 0 -pad 3
我们使用 columnconfigure
和 rowconfigure
命令来定义网格列和行中的一些空间。这样我们就可以实现按钮之间有一些空间。

Windows 示例
以下示例使用 grid 几何管理器创建 windows 对话框。对话框来自 JDeveloper 应用程序。
#!/usr/bin/wish # ZetCode Tcl/Tk tutorial # # In this script, we use the grid # manager to create a more complicated # layout. # # Author: Jan Bodnar # 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
小部件和四个按钮。
label .fr.lbl -text Windows grid .fr.lbl -sticky w -pady 4 -padx 5
创建 label 小部件并将其放入网格中。如果未指定列和行,则假定第一列或第一行。标签粘在西边,并且在其文本周围有一些填充。
text .fr.area grid .fr.area -row 1 -column 0 -columnspan 2 \ -rowspan 4 -padx 5 -sticky ewsn
创建 text
小部件并从第二行第一列开始。它跨越 2
列和 4
行。小部件和根窗口的左边框之间有 4px
的空间。最后,它粘在所有四个边上。因此,当调整窗口大小时,text
小部件在所有方向上增长。
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
小部件和按钮之间。

在本 Tcl/Tk 教程中,我们提到了小部件的布局管理。