本书红线(贯穿全教程,回顾):
1. 每个界面都用class App:封装,__init__里建控件,方法即事件回调。
2. 所有控件示例一律写在类里,不用脱离类的扁平脚本。
3. 代码块带if __name__ == "__main__":守卫,可独立运行。
4. 星级:★ 了解 · ★★ 理解 · ★★★ 掌握 · ★★★★ 重点必会。
主线项目:图形界面通讯录管理器,随章节每章新增一个控件慢慢长大。
上节回顾(第 1 章):你写出了第一个窗口,学会了用类(App)封装界面、用 self.root 保存窗口、用 if __name__ == "__main__": 守卫启动。本章认识第一个控件——Label(文字标签)。
本章目标:认识你的第一个控件——Label(文字标签)。它只负责"显示文字或图片",本身不交互(你不能点它、不能往里打字)。学会在类里创建它、设置字体颜色、换行、加边框,以及用 config() 在程序运行时改它的内容。
是什么:Label 是 tkinter 里最简单的控件之一,用来显示一段只读的文字(或图片)。它像一张贴纸,贴在窗口上给人看。
适用场景:
不适用:需要用户输入的场合用 Entry;需要点击触发动作的用 Button。
创建 Label 时可以传入很多选项来设定外观。下面这张表来自 Python 官方 tkinter 文档中 Label 支持的标准选项,挑最常用的列出(完整列表见官方文档 tkinter.Label):
| 选项 | 作用 | 常用取值 | 重要度 |
|---|---|---|---|
text | 显示的文本 | 字符串,如 "我的通讯录" | ★★★★ |
font | 字体与字号 | 元组 ("微软雅黑", 16) 或 "Arial 14 bold" | ★★★ |
fg | 文字颜色(foreground) | 颜色名 "red" 或 "#ff0000" | ★★★ |
bg | 背景颜色(background) | 同上 | ★★★ |
anchor | 文字在控件内的对齐 | "n"/"s"/"w"/"e"/"center"(上/下/左/右/中) | ★★ |
wraplength | 超过多少像素自动换行 | 像素数,如 200 | ★★ |
justify | 多行文本的对齐方式 | "left"/"center"/"right" | ★★ |
compound | 图文混排时文字相对图片的位置 | "top"/"bottom"/"left"/"right"/"center" | ★ |
relief | 边框样式 | "flat"(默认)/"groove"/"ridge"/"sunken"/"raised" | ★★ |
padx / pady | 文字到边框的内边距(左右 / 上下) | 像素数,如 10 | ★★ |
width / height | 控件宽度 / 高度(字符数,非像素) | 整数,如 20 | ★★ |
image | 显示的图片(需 PhotoImage) | tk.PhotoImage(...) | ★(后续章节详讲) |
textvariable | 绑定一个 StringVar,变量变文字跟着变 | tk.StringVar() | ★★★(后续章节详讲) |
📌fg/bg小知识:fg是 foreground(前景,即文字)的缩写;bg是 background。也可以用全称foreground=/background=,效果一样。
Label 继承自 tkinter 的 Widget 基类,因此它拥有所有控件通用的几个方法。下面是最常用的:
| 方法 | 作用 | 示例 |
|---|---|---|
config() / configure() | 运行时修改选项(两者完全相同) | label.config(text="新文字") |
cget("选项名") | 读取某个选项当前的值 | label.cget("text") → 返回当前文字 |
pack() / grid() / place() | 把控件放进窗口并排布(布局章节详讲) | label.pack() |
destroy() | 销毁(移除)这个控件 | label.destroy() |
winfo_width() / winfo_height() | 获取控件实际宽/高(像素) | label.winfo_width() |
after(ms, func) | 延时 ms 毫秒后执行 func(后续章节详讲) | label.after(2000, 改文字的函数) |
bind("<事件>", func) | 绑定事件(后续章节详讲) | label.bind("<Button-1>", 点击处理函数) |
关键认知:"创建时传选项"和"运行时用config()改选项"是同一件事的两种时机。创建时定初值,运行中想变就config()。
本书红线:示例一律写在类里。下面每个例子都是"完整可运行"的——复制即可跑(在本机运行,会弹出窗口)。
# 第2章 例2.1:在窗口里显示一个标题文字
import tkinter as tk
class App:
def __init__(self, root):
self.root = root
self.root.title("通讯录管理器")
# 创建一个 Label,text 选项是它要显示的文字;然后用 pack() 把它放进窗口
self.title_label = tk.Label(self.root, text="我的通讯录")
self.title_label.pack() # 不写布局语句,控件不会显示出来!
if __name__ == "__main__":
root = tk.Tk()
App(root)
root.mainloop()逐行说明:
self.title_label = tk.Label(self.root, text="我的通讯录"):在 self.root 这个窗口里创建 Label,显示"我的通讯录"。重点——把它存进 self.title_label,以后在类的别的方法里想改它,写 self.title_label.config(...) 即可。self.title_label.pack():布局语句。Label 创建后只是"存在",必须调用 pack()/grid()/place() 之一,它才真正出现在窗口上。忘了这行,窗口里啥都没有。# 第2章 例2.2:设置字体、文字颜色、背景色
import tkinter as tk
class App:
def __init__(self, root):
self.root = root
self.root.title("通讯录管理器")
self.title_label = tk.Label(
self.root,
text="我的通讯录",
font=("微软雅黑", 16), # 字体元组:(字体名, 字号);Windows 常用"微软雅黑"
fg="white", # 文字颜色:白
bg="#3a7afe", # 背景色:蓝(十六进制 #rrggbb)
padx=20, pady=10, # 文字到边框的内边距:左右20、上下10像素
)
self.title_label.pack()
if __name__ == "__main__":
root = tk.Tk()
App(root)
root.mainloop()说明:
font=("微软雅黑", 16):字体是元组,第一项是字体名、第二项是字号。也可以写字符串 "微软雅黑 16 bold"(bold 表示加粗)。fg="white" / bg="#3a7afe":颜色可用英文色名("red"、"blue"、"white"…)或十六进制("#ff0000" 红)。推荐用十六进制,配色更自由。padx/pady:让文字不贴边,更好看。# 第2章 例2.3:长句子用 wraplength 自动换行
import tkinter as tk
class App:
def __init__(self, root):
self.root = root
self.root.title("通讯录管理器")
self.tip = tk.Label(
self.root,
text="这是一个比较长的提示文字,超过指定宽度后会自动换行显示,避免一行摊得太长。",
wraplength=200, # 超过 200 像素就换行
justify="left", # 多行时左对齐
)
self.tip.pack(padx=10, pady=10)
if __name__ == "__main__":
root = tk.Tk()
App(root)
root.mainloop()说明:wraplength=200 表示文字宽度超过 200 像素就自动折行;justify="left" 控制折行后各行左对齐(默认也是左,但显式写出更清晰)。
# 第2章 例2.4:用 relief 给 Label 加边框,常用来做"分组标题"效果
import tkinter as tk
class App:
def __init__(self, root):
self.root = root
self.root.title("通讯录管理器")
self.box = tk.Label(
self.root,
text="基本信息",
relief="groove", # 凹线边框样式
borderwidth=2, # 边框粗细(像素)
padx=10, pady=5,
)
self.box.pack(padx=10, pady=10)
if __name__ == "__main__":
root = tk.Tk()
App(root)
root.mainloop()说明:relief 控制边框外观,"groove"(凹槽)、"ridge"(凸脊)、"sunken"(下沉)、"raised"(凸起)、"flat"(无,默认)。配合 borderwidth 调整粗细。
config() 改文字 ★★★本节还没讲按钮,我们用 after() 让文字"延时自动变",演示 config() 的用法(后续章节会正式讲 after,这里先感受"运行时改控件"):
# 第2章 例2.5:程序运行 2 秒后,自动把 Label 文字改掉(演示 config 运行时修改)
import tkinter as tk
class App:
def __init__(self, root):
self.root = root
self.root.title("通讯录管理器")
self.msg = tk.Label(self.root, text="正在加载…", font=("微软雅黑", 14))
self.msg.pack(padx=20, pady=20)
# after(2000, 函数):2000 毫秒(2秒)后,执行 self.change_text
self.root.after(2000, self.change_text)
def change_text(self): # 注意:这是类的方法,第一个参数是 self
self.msg.config(text="加载完成!") # 运行时修改文字,不用重建控件
if __name__ == "__main__":
root = tk.Tk()
App(root)
root.mainloop()逐行说明:
self.root.after(2000, self.change_text):tkinter 内置的"定时器"。2 秒后自动调用 self.change_text 这个方法。def change_text(self)::这是 App 类的一个方法。它不靠按钮触发,而是被 after 定时触发——但你先记住"它是类里的一个函数,第一个参数永远是 self"。self.msg.config(text="加载完成!"):运行时修改控件。原来显示"正在加载…",2 秒后变成"加载完成!"。这就是 config() 的威力:控件创建后,随时能改它的任何选项。运行例 2.5,你会先看到"正在加载…",2 秒后变成"加载完成!"——这证明了"界面上的东西是活的,能用代码随时改"。
本章反复出现的一行 self.title_label = tk.Label(...) 是 OOP 写法的核心习惯:
tk.Label(...) 返回一个 Label 对象,不是一段死文字。self:把它赋值给 self.xxx,这个控件就"挂"在了 App 实例上。类里任何方法(如例 2.5 的 change_text)都能通过 self.xxx 拿到它、改它。label 写成全局变量,函数之间传来传去。用类,所有控件都收在 self 下,结构一目了然。一句话:"界面上的每个控件,都是 self 的一个属性。" 这习惯从本章起贯穿全书。
font 写成字符串拼错:font="微软雅黑,16"(用逗号)是错的;正确是元组 ("微软雅黑", 16) 或字符串 "微软雅黑 16"(空格)。fg/bg 颜色拼写或格式错:"#3a7afe" 是 6 位十六进制;少一位(如 #3a7a)会报错。wraplength 单位搞混:它是像素,不是字符数。想按字符换行要用别的方式。config() 和 cget() 混淆:config(text="x") 是"设",cget("text") 是"读"。想取当前文字用 cget。image= 时必须先把 PhotoImage 对象存到 self(否则被回收),这是后续章节的坑,本章先用 text 即可。relief="raised" 和 borderwidth=3 给文字加个凸起边框。wraplength=150 显示一段不少于 30 字的话,观察它如何换行。self.msg.config(text="加载完成!") 写成 self.msg = tk.Label(self.root, text="加载完成!").pack() 会怎样?(提示:.pack() 返回 None,这样 self.msg 会变成 None,后面再 config 就报错。所以"创建并赋值"和"布局"要分开写。)下节预告:第 3 章我们认识第二个控件——Button(按钮),它是第一个"能交互"的控件:点一下就触发动作,并正式引入"方法即回调"这一 OOP 核心范式。