[Tkinter 教程] 布局管理 (Pack Place Grid)

原系列地址: Python Tkinter

简介:

本文讲述如何使用 tkinter 的布局管理 (被称作 layout managers 或 geometry managers). tkinter 有三种布局管理方式:

  • pack
  • grid
  • place

注意这三种布局管理在同一个 master window 里一定不可以混用! 布局管理有以下功能:

  • 将控件放置在屏幕上,包括控件的位置及控件的大小
  • 将控件注册到本地窗口系统中
  • 管理控件在屏幕上的显示

虽然控件自己也可以指定大小和对齐方式等信息, 但最终的控件大小及位置还是由布局管理决定的.

Pack 布局管理

pack 是三种布局管理中最常用的. 另外两种布局需要精确指定控件具体的显示位置, 而 pack 布局可以指定相对位置, 精确的位置会由 pack 系统自动完成. 这也使得 pack 布局没有另外两种布局方式灵活. 所以 pack 是简单应用的首选布局, 比如只是想要将控件水平或垂直的逐个放在一起:

[python] view plain copy
 
  1. from Tkinter import *  
  2.   
  3. root = Tk()  
  4.   
  5. Label(root, text="Red Sun", bg="red", fg="white").pack()  
  6. Label(root, text="Green Grass", bg="green", fg="black").pack()  
  7. Label(root, text="Blue Sky", bg="blue", fg="white").pack()  
  8.   
  9. mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

下面将逐一讲解 pack 布局的各个属性.

fill 控件填充方式

在上面那个例子里, 我们简单的将三个 Label 控件 pack 到其父窗口上, 没有使用任何属性. 于是 pack 使用了默认方式进行布局: 从上到下顺次排放, 并水平居中. 同时我们也发现, pack 默认会将 Label 控件的宽度设置为其中的文字的宽度. 如果我们想让它们和其父窗口一样宽, 可以使用 fill=X 属性:

[python] view plain copy
 
  1. from Tkinter import *  
  2.   
  3. root = Tk()  
  4.   
  5. w = Label(root, text="Red Sun", bg="red", fg="white")  
  6. w.pack(fill=X)  
  7. w = Label(root, text="Green Grass", bg="green", fg="black")  
  8. w.pack(fill=X)  
  9. w = Label(root, text="Blue Sky", bg="blue", fg="white")  
  10. w.pack(fill=X)  
  11.   
  12. mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

padding 控件边距

Pack 可以在四个方面控制控件边距: 内边距, 外边距, 水平边距, 垂直边距:

padx - 设置水平方向的外边距

[python] view plain copy
 
  1. from Tkinter import *  
  2. root = Tk()  
  3. w = Label(root, text="Red Sun", bg="red", fg="white")  
  4. w.pack(fill=X,padx=10)  
  5. w = Label(root, text="Green Grass", bg="green", fg="black")  
  6. w.pack(fill=X,padx=10)  
  7. w = Label(root, text="Blue Sky", bg="blue", fg="white")  
  8. w.pack(fill=X,padx=10)  
  9. mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

pady - 设置竖直方向的外边距

[python] view plain copy
 
  1. from Tkinter import *  
  2. root = Tk()  
  3. w = Label(root, text="Red Sun", bg="red", fg="white")  
  4. w.pack(fill=X,pady=10)  
  5. w = Label(root, text="Green Grass", bg="green", fg="black")  
  6. w.pack(fill=X,pady=10)  
  7. w = Label(root, text="Blue Sky", bg="blue", fg="white")  
  8. w.pack(fill=X,pady=10)  
  9. mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

ipadx - 设置水平方向的内边距

[python] view plain copy
 
  1. from Tkinter import *  
  2. root = Tk()  
  3. w = Label(root, text="Red Sun", bg="red", fg="white")  
  4. w.pack()  
  5. w = Label(root, text="Green Grass", bg="green", fg="black")  
  6. w.pack(ipadx=10)  
  7. w = Label(root, text="Blue Sky", bg="blue", fg="white")  
  8. w.pack()  
  9. mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

ipady - 设置竖直方向的内边距

[python] view plain copy
 
  1. from Tkinter import *  
  2. root = Tk()  
  3. w = Label(root, text="Red Sun", bg="red", fg="white")  
  4. w.pack()  
  5. w = Label(root, text="Green Grass", bg="green", fg="black")  
  6. w.pack(ipadx=10)  
  7. w = Label(root, text="Blue Sky", bg="blue", fg="white")  
  8. w.pack(ipady=10)  
  9. mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

上述四个属性的默认值都是 0.

side 顺次放置控件

我们把上面那几个 Label 从左到右放在一排:

[python] view plain copy
 
  1. from Tkinter import *  
  2.   
  3. root = Tk()  
  4.   
  5. w = Label(root, text="red", bg="red", fg="white")  
  6. w.pack(padx=5, pady=10, side=LEFT)  
  7. w = Label(root, text="green", bg="green", fg="black")  
  8. w.pack(padx=5, pady=20, side=LEFT)  
  9. w = Label(root, text="blue", bg="blue", fg="white")  
  10. w.pack(padx=5, pady=20, side=LEFT)  
  11.   
  12. mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

如果把上述 side 属性的值都改为 RIGHT, 那么上面 Label 控件的排列顺序就反过来了:

[Tkinter 教程] 布局管理 (Pack Place Grid)

Place 布局管理

Place 布局管理可以显式的指定控件的绝对位置或相对于其他控件的位置. 要使用 Place 布局, 调用相应控件的 place() 方法就可以了. 所有 tkinter 的标准控件都可以调用 place()

 方法.

下面是一个使用 Place 布局的例子: 为 Label 控件设置随机的背景色, 然后计算各个 Label 的背景色的亮度(灰度值), 如果其亮度小于 120, 则将其前景色(文字颜色, fg属性)设置为白色, 否则设为黑色. 这样做是为了避免使背景色和前景色过于接近而导致文字不易阅读.

[python] view plain copy
 
  1. import Tkinter as tk  
  2. import random  
  3.       
  4. root = tk.Tk()  
  5. # width x height + x_offset + y_offset:  
  6. root.geometry("170x200+30+30")   
  7.        
  8. languages = ['Python','Perl','C++','Java','Tcl/Tk']  
  9. labels = range(5)  
  10. for i in range(5):  
  11.    ct = [random.randrange(256) for x in range(3)]  
  12.    brightness = int(round(0.299*ct[0] + 0.587*ct[1] + 0.114*ct[2]))  
  13.    ct_hex = "%02x%02x%02x" % tuple(ct)  
  14.    bg_colour = '#' + "".join(ct_hex)  
  15.    l = tk.Label(root,   
  16.                 text=languages[i],   
  17.                 fg='White' if brightness < 120 else 'Black',   
  18.                 bg=bg_colour)  
  19.    l.place(x = 20, y = 30 + i*30, width=120, height=25)  
  20.             
  21. root.mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

Grid 布局管理

Pack 作为首选的布局管理方式, 其运作方式并不是特别易于理解. 已经由 Pack 布局完成的设计也很难做出改变. Grid 布局在1996年作为另一种可供选择的布局方式被引入. Grid 布局方式易学易用, 但似乎大家还是习惯用 Pack.

Grid 在很多场景下是最好用的布局方式. 相比而言, Pack 布局在控制细节方面有些力不从心. Place 布局虽然可以完全控制控件位置, 但这也导致使用 Place 会比其他两种布局方式更加复杂.

Grid 把控件位置作为一个二维表结构来维护, 即按照行列的方式排列控件: 控件位置由其所在的行号和列号决定. 行号相同而列号不同的几个控件会被彼此上下排列; 列号相同而行号不同的几个控件会被彼此左右排列.

使用 Grid 布局的过程就是为各个控件指定行号和列号的过程. 不需要为每个格子指定大小, Grid 布局会自动设置一个合适的大小.

下面还是举个栗子吧:

[python] view plain copy
 
  1. from Tkinter import *  
  2.   
  3. colours = ['red','green','orange','white','yellow','blue']  
  4.   
  5. r = 0  
  6. for c in colours:  
  7.     Label(text=c, relief=RIDGE,width=15).grid(row=r,column=0)  
  8.     Entry(bg=c, relief=SUNKEN,width=10).grid(row=r,column=1)  
  9.     r = r + 1  
  10.   
  11. mainloop()  

[Tkinter 教程] 布局管理 (Pack Place Grid)

译者水平有限, 如有疏漏, 欢迎指正.

已获得原作者授权. 原文地址: Layout Management