30天学会Python编程:22.Python图形化编程,Tkinter实践指南
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
|
# 垂直排列
label1.pack()
label2.pack()
# 水平排列
button1.pack(side=tk.LEFT)
button2.pack(side=tk.LEFT)
# 网格布局
label.grid(row=0, column=0)
entry.grid(row=0, column=1)
button.grid(row=1, column=0, columnspan=2)
# 绝对位置
button.place(x=100, y=50)
# 相对位置
button.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
def on_click():
print("按钮被点击!")
button = tk.Button(root, text="点击我", command=on_click)
def on_key(event):
print(f"按键: {event.char}")
root.bind("<Key>", on_key)
<Button-1>:鼠标左键点击
<Key>:键盘按键
<Motion>:鼠标移动
<Configure>:窗口大小变化
class Tk(Misc, Wm):
def __init__(self, screenName=None, baseName=None, className='Tk'):
...
功能:创建应用程序主窗口
主要方法:
title(text):设置窗口标题
geometry(size):设置窗口大小("宽x高")
resizable(width, height):设置窗口是否可调整大小
mainloop():启动主事件循环
注意事项:
widget.pack(options) # pack布局
widget.grid(options) # grid布局
widget.place(options) # place布局
widget.config(**options) # 配置组件属性
widget.bind(sequence, func) # 绑定事件
text_var = tk.StringVar()
entry = tk.Entry(root, textvariable=text_var)
# 获取值
current_text = text_var.get()
# 设置值
text_var.set("新文本")
功能:将组件与变量动态绑定
应用场景:实时同步输入内容、自动更新界面
import tkinter as tk
from tkinter import ttk, messagebox
import json
import os
classStudentManager:
"""学生信息管理系统"""
def__init__(self, root):
self.root = root
self.root.title("学生信息管理系统")
self.root.geometry("800x600")
self.students = []
self.data_file = "students.json"
self.load_data()
self.create_widgets()
defcreate_widgets(self):
"""创建界面组件"""
# 创建菜单栏
menubar = tk.Menu(self.root)
self.root.config(menu=menubar)
# 文件菜单
file_menu = tk.Menu(menubar, tearoff=0)
file_menu.add_command(label="保存", command=self.save_data)
file_menu.add_command(label="退出", command=self.root.quit)
menubar.add_cascade(label="文件", menu=file_menu)
# 工具栏
toolbar = ttk.Frame(self.root)
toolbar.pack(fill=tk.X, padx=5, pady=5)
add_btn = ttk.Button(toolbar, text="添加", command=self.add_student)
add_btn.pack(side=tk.LEFT, padx=2)
del_btn = ttk.Button(toolbar, text="删除", command=self.delete_student)
del_btn.pack(side=tk.LEFT, padx=2)
# 搜索区域
search_frame = ttk.Frame(self.root)
search_frame.pack(fill=tk.X, padx=5, pady=5)
ttk.Label(search_frame, text="搜索:").pack(side=tk.LEFT)
self.search_var = tk.StringVar()
search_entry = ttk.Entry(search_frame, textvariable=self.search_var)
search_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
search_entry.bind("<KeyRelease>", self.search_student)
# 学生列表
list_frame = ttk.Frame(self.root)
list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
columns = ("id", "name", "score")
self.tree = ttk.Treeview(
list_frame, columns=columns, show="headings", selectmode="browse"
)
# 设置列标题
self.tree.heading("id", text="学号")
self.tree.heading("name", text="姓名")
self.tree.heading("score", text="成绩")
# 设置列宽
self.tree.column("id", width=100, anchor=tk.CENTER)
self.tree.column("name", width=200, anchor=tk.W)
self.tree.column("score", width=100, anchor=tk.CENTER)
# 添加滚动条
scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.tree.yview)
self.tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.tree.pack(fill=tk.BOTH, expand=True)
# 绑定选择事件
self.tree.bind("<<TreeviewSelect>>", self.on_select)
# 信息表单
form_frame = ttk.LabelFrame(self.root, text="学生信息")
form_frame.pack(fill=tk.X, padx=5, pady=5)
# 学号
ttk.Label(form_frame, text="学号:").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
self.id_var = tk.StringVar()
id_entry = ttk.Entry(form_frame, textvariable=self.id_var)
id_entry.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W+tk.E)
# 姓名
ttk.Label(form_frame, text="姓名:").grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
self.name_var = tk.StringVar()
name_entry = ttk.Entry(form_frame, textvariable=self.name_var)
name_entry.grid(row=1, column=1, padx=5, pady=5, sticky=tk.W+tk.E)
# 成绩
ttk.Label(form_frame, text="成绩:").grid(row=2, column=0, padx=5, pady=5, sticky=tk.W)
self.score_var = tk.StringVar()
score_entry = ttk.Entry(form_frame, textvariable=self.score_var)
score_entry.grid(row=2, column=1, padx=5, pady=5, sticky=tk.W+tk.E)
# 按钮区域
btn_frame = ttk.Frame(self.root)
btn_frame.pack(fill=tk.X, padx=5, pady=10)
save_btn = ttk.Button(btn_frame, text="保存", command=self.save_student)
save_btn.pack(side=tk.RIGHT, padx=5)
clear_btn = ttk.Button(btn_frame, text="清空", command=self.clear_form)
clear_btn.pack(side=tk.RIGHT, padx=5)
# 加载数据到列表
self.load_to_treeview()
defload_data(self):
"""从文件加载数据"""
if os.path.exists(self.data_file):
try:
withopen(self.data_file, 'r', encoding='utf-8') as f:
self.students = json.load(f)
except Exception as e:
messagebox.showerror("错误", f"加载数据失败: {str(e)}")
self.students = []
defsave_data(self):
"""保存数据到文件"""
try:
withopen(self.data_file, 'w', encoding='utf-8') as f:
json.dump(self.students, f, ensure_ascii=False, indent=2)
messagebox.showinfo("成功", "数据保存成功!")
except Exception as e:
messagebox.showerror("错误", f"保存数据失败: {str(e)}")
defload_to_treeview(self):
"""加载数据到Treeview"""
# 清空现有数据
for item inself.tree.get_children():
self.tree.delete(item)
# 添加新数据
for student inself.students:
self.tree.insert("", tk.END, values=(
student["id"],
student["name"],
student["score"]
))
defadd_student(self):
"""添加学生"""
self.clear_form()
self.id_var.set(self.generate_id())
defgenerate_id(self):
"""生成学号"""
ifnotself.students:
return"S001"
max_id = max(int(s["id"][1:]) for s inself.students)
returnf"S{max_id + 1:03d}"
defsave_student(self):
"""保存学生信息"""
ifnotself.validate_form():
return
student = {
"id": self.id_var.get(),
"name": self.name_var.get(),
"score": self.score_var.get()
}
# 检查是否已存在
existing_ids = [s["id"] for s inself.students]
if student["id"] in existing_ids:
# 更新现有记录
for i, s inenumerate(self.students):
if s["id"] == student["id"]:
self.students[i] = student
break
else:
# 添加新记录
self.students.append(student)
self.load_to_treeview()
self.clear_form()
messagebox.showinfo("成功", "学生信息已保存!")
defvalidate_form(self):
"""验证表单数据"""
ifnotself.id_var.get():
messagebox.showwarning("警告", "学号不能为空!")
returnFalse
ifnotself.name_var.get():
messagebox.showwarning("警告", "姓名不能为空!")
returnFalse
try:
float(self.score_var.get())
except ValueError:
messagebox.showwarning("警告", "成绩必须是数字!")
returnFalse
returnTrue
defon_select(self, event):
"""选中学生时加载到表单"""
selected = self.tree.selection()
ifnot selected:
return
item = self.tree.item(selected[0])
values = item["values"]
self.id_var.set(values[0])
self.name_var.set(values[1])
self.score_var.set(values[2])
defdelete_student(self):
"""删除选中学生"""
selected = self.tree.selection()
ifnot selected:
messagebox.showwarning("警告", "请先选择一个学生!")
return
ifnot messagebox.askyesno("确认", "确定要删除该学生记录吗?"):
return
item = self.tree.item(selected[0])
student_id = item["values"][0]
# 从数据中删除
self.students = [s for s inself.students if s["id"] != student_id]
# 从Treeview删除
self.tree.delete(selected[0])
self.clear_form()
defsearch_student(self, event):
"""搜索学生"""
keyword = self.search_var.get().lower()
# 清空当前显示
for item inself.tree.get_children():
self.tree.delete(item)
# 添加匹配项
for student inself.students:
if (keyword in student["id"].lower() or
keyword in student["name"].lower() or
keyword in student["score"].lower()):
self.tree.insert("", tk.END, values=(
student["id"],
student["name"],
student["score"]
))
defclear_form(self):
"""清空表单"""
self.id_var.set("")
self.name_var.set("")
self.score_var.set("")
self.tree.selection_remove(self.tree.selection())
if __name__ == "__main__":
root = tk.Tk()
app = StudentManager(root)
root.mainloop()
数据管理:
界面特点:
用户体验:
from tkinter import ttk
# 使用ttk主题
style = ttk.Style()
style.theme_use("clam") # 可选: 'clam', 'alt', 'default', 'classic'
# 自定义样式
style.configure("Custom.TButton",
foreground="blue",
font=("Arial", 12),
padding=10)
# 应用样式
button = ttk.Button(root, text="美化按钮", style="Custom.TButton")
canvas = tk.Canvas(root, width=400, height=300)
canvas.pack()
# 绘制图形
canvas.create_rectangle(50, 50, 150, 150, fill="blue")
canvas.create_oval(200, 100, 300, 200, fill="red")
canvas.create_line(0, 0, 400, 300, width=2, fill="green")
def open_dialog():
dialog = tk.Toplevel(root)
dialog.title("对话框")
dialog.geometry("300x200")
tk.Label(dialog, text="这是一个对话框").pack(pady=20)
ttk.Button(dialog, text="关闭", command=dialog.destroy).pack()
btn = ttk.Button(root, text="打开对话框", command=open_dialog)
btn.pack(pady=20)
代码组织:
错误处理:
用户体验:
性能优化:
深入学习:
项目实践:
进阶方向:
提示:GUI开发的核心不仅是技术实现,更是对用户体验的理解和尊重。好的界面应该让用户感到自然、高效和愉悦。
通过本教程,我们可以掌握Tkinter的核心概念和实践技巧。后续可以通过实际项目不断练习,提升熟练度和解决实际问题的能力!
阅读原文:原文链接