《零基础入门学习Python》第076讲:GUI的终极选择:Tkinter13

这节课我们来学习 Tkinter 的布局管理器,那什么是布局管理器呢?说白了,就是用于管理你的组件如何排列。Tkinter 提供了 3 大布局管理器:pack、grid 和 place。

  • pack 是按添加顺序排列组件
  • grid 是按行/列形式排列组件
  • place 则允许程序员指定组件的大小和位置

(一)pack 管理器

对比 grid 管理器,pack 更适用于少量组件的排列,但它在使用上更加简单(就像我们前边所有的例子中,展示一个组件我们一般都直接使用 .pack(),多简单~)。如果你需要创建相对复杂的布局结构,那么建议是使用多个框架(Frame)结构构成,或者使用 grid 管理器实现。

注意:不要在同一个父组件中混合使用 pack 和 grid,因为 Tkinter 会很认真地在那儿计算到底先使用那个布局管理器......以至于你等了半个小时,Tkinter 还在那儿纠结不出结果!

我们来给大家举个例子:

我们常常会遇到一个情况就是 将一个组件放进另一个组件里,并且要求是填充另一个组件,那我们要怎么做呢?

我们先用 pack 来演示:

 
  
  1. import tkinter as tk

  2. root = tk.Tk()

  3. listbox = tk.Listbox(root)

  4. listbox.pack(fill = "both", expand = True)

  5. for i in range(10):

  6. listbox.insert("end", str(i))

  7. root.mainloop()

其中,fill 选项是告诉窗口管理器该组件将填充整个分配给它的空间,"both" 表示同时横向和纵向扩展,"x" 表示横向,"y" 表示纵向;expand 选项是告诉窗口管理器将父组件的额外空间也填满。

刚才我们说了,pack 是按照组件的添加顺序依次排列的,那么它依次是纵向排列呢,还是横向排列呢?我们做一个演示:

 
  
  1. import tkinter as tk

  2. root = tk.Tk()

  3. tk.Label(root, text="Red", bg="red", fg="white").pack(fill="x")

  4. tk.Label(root, text="Green", bg="green", fg="black").pack(fill="x")

  5. tk.Label(root, text="Blue", bg="blue", fg="white").pack(fill="x")

  6. root.mainloop()

《零基础入门学习Python》第076讲:GUI的终极选择:Tkinter13_第1张图片

我们可以看到,是纵向填充的。如果想要组件横向挨个儿排放,你可以使用 side 选项:

 
  
  1. import tkinter as tk

  2. root = tk.Tk()

  3. tk.Label(root, text="Red", bg="red", fg="white").pack(side = "left")

  4. tk.Label(root, text="Green", bg="green", fg="black").pack(side = "left")

  5. tk.Label(root, text="Blue", bg="blue", fg="white").pack(side = "left")

  6. root.mainloop()

(二)grid 管理器

grid 管理器可以说是 Tkinter 这三个布局管理器中最灵活多变的。如果你只希望学习使用一个布局管理器,那么 grid 绝对是首选。当你在设计对话框的时候,使用 gird 尤其便捷。如果你此前一直在用 pack 构造窗口布局,那么学习完 grid 你会悔恨当初为啥不早学它。使用一个 grid 就可以简单的实现你用很多个框架和 pack 搭建起来的效果。

注意:不要在同一个父组件中混合使用 pack 和 grid,因为 Tkinter 会很认真地在那儿计算到底先使用那个布局管理器......以至于你等了半个小时,Tkinter 还在那儿纠结不出结果!

我们还是举例说明:

使用 grid 排列组件,只需告诉它你想要将组件放置的位置(行/列,row 选项指定行,cloumn 选项指定列)。此外,你并不用提前指出网格(grid 分布给组件的位置称为网格)的尺寸,因为管理器会自动计算。

 
  
  1. import tkinter as tk

  2. root = tk.Tk()

  3. # column 默认值是 0

  4. tk.Label(root, text="用户名").grid(row=0)

  5. tk.Label(root, text="密码").grid(row=1)

  6. tk.Entry(root).grid(row=0, column=1)

  7. tk.Entry(root, show="*").grid(row=1, column=1)

  8. root.mainloop()

默认情况下组件会居中显示在对应的网格里,你可以使用 sticky 选项来修改这一特性。该选项可以使用的值有 "e","w","s","n"(ewsn 分别表示东西南北,即上北下南左西右东)以及它们的组合。因此,我们可以通过 sticky = "w" 使得 Label 左对齐:

 
  
  1. tk.Label(root, text="用户名").grid(row=0, sticky="w")

  2. tk.Label(root, text="密码").grid(row=1, sticky="w")

有时候你可能需要用几个网格来放置一个组件,可以做到吗?当然可以,你只需要指定 rowspan 和 columnspan 就可以实现跨行和跨列的功能:

 
  
  1. import tkinter as tk

  2. root = tk.Tk()

  3. # column 默认值是 0

  4. tk.Label(root, text="用户名").grid(row=0, sticky="w")

  5. tk.Label(root, text="密码").grid(row=1, sticky="w")

  6. tk.Entry(root).grid(row=0, column=1)

  7. tk.Entry(root, show="*").grid(row=1, column=1)

  8. photo = tk.PhotoImage(file="logo.gif")

  9. tk.Label(root, image=photo).grid(row=0, column=2, rowspan=2, padx=5, pady=5) #跨两行

  10. tk.Button(text="提交", width=10).grid(row=2, columnspan=3, pady=5) #跨3列

  11. root.mainloop()

(二)place 管理器

通常情况下不建议使用 place 布局管理器,因为对比起 pack 和 grid,place 要做更多的工作。不过存在即合理,place 在一些特殊的情况下可以发挥妙用。请看下边例子。

比如 我想 :将子组件显示在父组件的正中间:

 
  
  1. import tkinter as tk

  2. root = tk.Tk()

  3. def callback():

  4. print("正中靶心")

  5. tk.Button(root, text="点我", command=callback).place(relx=0.5, rely=0.5, anchor="center")

  6. root.mainloop()

relx 和 rely 就是相对于 父组件的水平位置 和 垂直位置; anchor="center" 表示居中显示。

在某种情况下,或许你希望一个组件可以覆盖另一个组件,那么 place 又可以派上用场了。下边例子我们演示用 Button 覆盖 Label 组件:

 
  
  1. import tkinter as tk

  2. root = tk.Tk()

  3. photo = tk.PhotoImage(file = "Python.gif")

  4. tk.Label(root, image = photo).pack()

  5. def callback():

  6. print("正中靶心")

  7. tk.Button(root, text="点我", command=callback).place(relx=0.5, rely=0.5, anchor="center")

  8. root.mainloop()

relx 和 rely 选项指定的是相对于父组件的位置,范围是 00 ~ 1.0,因此 0.5 表示位于正中间。那么 relwidth 和 relheight 选项则是指定相对于父组件的尺寸:

 
  
  1. import tkinter as tk

  2. root = tk.Tk()

  3. tk.Label(root, bg="red").place(relx=0.5, rely=0.5, relheight=0.75, relwidth=0.75, anchor="center")

  4. tk.Label(root, bg="yellow").place(relx=0.5, rely=0.5, relheight=0.5, relwidth=0.5, anchor="center")

  5. tk.Label(root, bg="green").place(relx=0.5, rely=0.5, relheight=0.25, relwidth=0.25, anchor="center")

  6. root.mainloop()

上图无论你如何拉伸改变窗口,三个 Label 的尺寸均会跟着改变(神同步~)。x 和 y 选项用于设置偏移(像素),如果同时设置 relx(rely)和 x(y),那 place 将优先计算 relx 和 rely,然后再实现 x 和 y 指定的偏移值。

关于这三个布局管理器的方法和其他选项,可以查看这三个组件的详解。(有分别介绍这三个组件全部内容的博客,下面是链接):

Tkinter 布局管理器(一):pack

Tkinter 布局管理器(二):grid

Tkinter 布局管理器(三):place

你可能感兴趣的:(python零基础,python)