第三节:控件与交互——Button、Label、Entry、Text实战
好,咱们直接进入正题。这一节我们要做一个最简单的登录界面。别小看它,登录框是几乎所有桌面应用和Web应用的标配。你想想看,你每天打开、邮箱、各种系统,第一眼看到的是什么?就是登录界面。
我个人习惯,学任何GUI框架,第一个实战项目就是登录界面。为什么?因为它涵盖了最核心的四个控件:Label(标签)、Entry(输入框)、Button(按钮)、Text(文本区域)。这四个控件用好了,你就能搞定80%的界面交互需求。
3.1 四个核心控件,各司其职
先简单过一遍这四个控件是干什么的。我当年刚学的时候,总把Label和Text搞混,后来踩了坑才明白——它们完全是两码事。
| 控件 | 作用 | 典型场景 |
|---|---|---|
| Label | 显示静态文本,用户不能修改 | 提示文字、标题、状态显示 |
| Entry | 单行文本输入框 | 用户名、密码、搜索框 |
| Button | 可点击的按钮,触发事件 | 登录、注册、取消、提交 |
| Text | 多行文本区域,可编辑 | 日志输出、留言板、协议展示 |
核心区别:Entry只能输入一行,Text可以输入多行。Label只能看不能改,Entry和Text既能看又能改。Button是唯一能触发动作的控件。
3.2 实战:手写一个登录界面
好,咱们直接上代码。我会带着你一步步写,每行代码我都会解释为什么这么写。
先创建一个Python文件,叫 login_demo.py。然后敲下面的代码:
import tkinter as tk
from tkinter import messagebox
# 创建主窗口
root = tk.Tk()
root.title("登录界面")
root.geometry("400x300")
root.resizable(False, False) # 固定窗口大小,不让用户乱拉
# 用户名区域
tk.Label(root, text="用户名:", font=("微软雅黑", 12)).place(x=50, y=60)
entry_username = tk.Entry(root, font=("微软雅黑", 12), width=20)
entry_username.place(x=150, y=60)
# 密码区域
tk.Label(root, text="密 码:", font=("微软雅黑", 12)).place(x=50, y=110)
entry_password = tk.Entry(root, font=("微软雅黑", 12), width=20, show="*")
entry_password.place(x=150, y=110)
# 登录按钮
def login():
username = entry_username.get()
password = entry_password.get()
if username == "admin" and password == "123456":
messagebox.showinfo("登录成功", "欢迎回来,管理员!")
else:
messagebox.showerror("登录失败", "用户名或密码错误")
btn_login = tk.Button(root, text="登录", font=("微软雅黑", 12),
command=login, bg="#4CAF50", fg="white")
btn_login.place(x=150, y=170)
# 运行主循环
root.mainloop()
嗯,这里要注意几个细节。我一个个说。
3.3 代码拆解:每一行都有讲究
第一,窗口设置。
root.resizable(False, False) 这行很多人会忽略。我曾经做过一个项目,用户反馈说「你们的登录窗口怎么可以拉成一条线?」——就是因为没锁窗口大小。你想想看,登录界面就那么几个控件,让用户随意拉伸,界面会变得很难看。所以,登录窗口一定要固定大小。
第二,密码输入框的 show 参数。
show="*" 这个参数是Entry独有的。它会把输入的内容显示成星号。我见过新手用Label来显示密码输入,结果密码明文显示在屏幕上——这要是被旁边的人看到,那可就尴尬了。
第三,按钮的 command 参数。
这是事件驱动的核心。按钮被点击时,会调用 login() 函数。注意,这里写的是 command=login,不是 command=login()。多了括号,函数会在创建按钮时立即执行,而不是等点击时才执行。这个坑我踩过不止一次。
小技巧:如果你想让按钮点击时传递参数,可以用 lambda。比如 command=lambda: login("admin")。这是Python闭包的经典用法,面试也常考。
3.4 事件驱动:按钮点击背后发生了什么
好,现在我们来聊聊「事件驱动」这个概念。说白了,就是程序在等待用户操作。用户不点按钮,程序就什么都不做。用户一点,程序立刻响应。
为什么会这样?因为 root.mainloop() 这个函数开启了一个事件循环。它就像一个大管家,24小时盯着屏幕,一旦检测到鼠标点击、键盘输入,就立刻去执行对应的回调函数。
我画了一张图,帮你理解这个流程:
这张图很直观。事件循环一直在后台跑着,用户一操作,它就捕获事件、分发事件、执行回调。整个过程一气呵成,毫秒级完成。
3.5 进阶:用Text控件显示日志
登录成功或失败,光弹个消息框太单调了。我们加一个Text控件,把操作日志显示出来。这样用户能看到「刚才发生了什么」。
# 在登录按钮下方加一个文本区域
log_text = tk.Text(root, font=("微软雅黑", 10), width=40, height=6,
state="disabled") # 初始状态不可编辑
log_text.place(x=50, y=220)
def login():
username = entry_username.get()
password = entry_password.get()
# 启用Text控件,写入日志,再禁用
log_text.config(state="normal")
if username == "admin" and password == "123456":
log_text.insert(tk.END, f"[{get_time()}] 登录成功\n")
messagebox.showinfo("登录成功", "欢迎回来,管理员!")
else:
log_text.insert(tk.END, f"[{get_time()}] 登录失败:用户名或密码错误\n")
messagebox.showerror("登录失败", "用户名或密码错误")
log_text.config(state="disabled")
log_text.see(tk.END) # 自动滚动到底部
def get_time():
from datetime import datetime
return datetime.now().strftime("%H:%M:%S")
注意:Text控件默认是可编辑的。如果你只想用它显示日志,一定要设置 state="disabled"。写入日志时先改成 normal,写完后立刻改回 disabled。否则用户可以在日志区域乱打字,那画面太美我不敢看。
3.6 避坑指南:我踩过的那些坑
做这个登录界面,有几个坑我当年都踩过,分享给你,省得你重走弯路。
- Entry的get()方法返回空字符串——最常见的问题。原因往往是你在窗口还没显示完就去取值。记住,一定要在事件回调里取值,不要在创建控件后立刻取值。
- 密码显示为明文——忘了加
show="*"。我有个同事因为这个被客户投诉了,说「你们的密码框是透明的吗?」 - 按钮点击没反应——检查
command参数有没有写括号。写了括号,函数在创建时执行,返回值赋给command,而不是函数本身。 - Text控件内容越写越多——如果不清理,日志会无限增长。建议加个限制,比如只保留最近100行。
3.7 完整代码整合
好,把上面所有代码整合到一起,就是一个完整的登录界面了。我建议你亲手敲一遍,不要复制粘贴。敲代码的过程,就是肌肉记忆形成的过程。
import tkinter as tk
from tkinter import messagebox
from datetime import datetime
root = tk.Tk()
root.title("登录界面")
root.geometry("400x350")
root.resizable(False, False)
# 用户名
tk.Label(root, text="用户名:", font=("微软雅黑", 12)).place(x=50, y=40)
entry_username = tk.Entry(root, font=("微软雅黑", 12), width=20)
entry_username.place(x=150, y=40)
# 密码
tk.Label(root, text="密 码:", font=("微软雅黑", 12)).place(x=50, y=90)
entry_password = tk.Entry(root, font=("微软雅黑", 12), width=20, show="*")
entry_password.place(x=150, y=90)
# 日志区域
log_text = tk.Text(root, font=("微软雅黑", 10), width=40, height=6, state="disabled")
log_text.place(x=50, y=200)
def get_time():
return datetime.now().strftime("%H:%M:%S")
def login():
username = entry_username.get()
password = entry_password.get()
log_text.config(state="normal")
if username == "admin" and password == "123456":
log_text.insert(tk.END, f"[{get_time()}] 登录成功\n")
messagebox.showinfo("登录成功", "欢迎回来,管理员!")
else:
log_text.insert(tk.END, f"[{get_time()}] 登录失败:用户名或密码错误\n")
messagebox.showerror("登录失败", "用户名或密码错误")
log_text.config(state="disabled")
log_text.see(tk.END)
# 登录按钮
btn_login = tk.Button(root, text="登录", font=("微软雅黑", 12),
command=login, bg="#4CAF50", fg="white")
btn_login.place(x=150, y=150)
root.mainloop()
运行这段代码,你会看到一个完整的登录界面。输入 admin 和 123456,点击登录,看看效果。
总结一下:这一节我们做了三件事——第一,学会了Label、Entry、Button、Text四个控件的用法;第二,理解了事件驱动的核心机制;第三,亲手写了一个带日志功能的登录界面。这些基础打牢了,后面做复杂界面就会轻松很多。
可可精品资料库