第17天-图形界面

2023/6/15

# 第17天-图形界面

# 学习目标

通过第17天的学习,你将掌握:

  1. GUI编程基础 - 理解图形界面编程的基本概念
  2. Tkinter框架 - 掌握Python内置GUI库的使用
  3. 控件使用 - 学会各种GUI控件的应用
  4. 事件处理 - 理解事件驱动编程模式
  5. 布局管理 - 掌握界面布局的设计方法
  6. 高级功能 - 学习菜单、对话框、画布等高级特性
  7. 实际项目 - 完成完整的GUI应用程序
  8. 其他GUI框架 - 了解PyQt、wxPython等替代方案

# 一、GUI编程基础

# 1.1 图形界面编程概述

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import threading
import time

def gui_programming_intro():
    """GUI编程基础概念介绍"""
    print("=== GUI编程基础概念 ===")
    
    # 1. GUI编程的基本概念
    print("\n1. GUI编程基本概念:")
    
    concepts = {
        "窗口(Window)": "应用程序的主容器,包含所有其他控件",
        "控件(Widget)": "用户界面的基本元素,如按钮、标签、文本框等",
        "事件(Event)": "用户操作或系统状态变化,如点击、键盘输入等",
        "事件处理器(Handler)": "响应特定事件的函数或方法",
        "布局管理器(Layout)": "控制控件在窗口中的位置和大小",
        "回调函数(Callback)": "当事件发生时被调用的函数"
    }
    
    for concept, description in concepts.items():
        print(f"    {concept}: {description}")
    
    # 2. 事件驱动编程模型
    print("\n2. 事件驱动编程模型:")
    
    event_model = [
        "程序启动 -> 创建GUI界面",
        "进入事件循环 -> 等待用户操作",
        "检测事件 -> 鼠标点击、键盘输入等",
        "调用事件处理器 -> 执行相应的处理函数",
        "更新界面 -> 刷新显示内容",
        "返回事件循环 -> 继续等待下一个事件"
    ]
    
    for i, step in enumerate(event_model, 1):
        print(f"    {i}. {step}")
    
    # 3. 常见GUI框架对比
    print("\n3. Python GUI框架对比:")
    
    frameworks = {
        "Tkinter": {
            "优点": ["内置库", "轻量级", "跨平台", "学习简单"],
            "缺点": ["外观较老", "控件有限", "性能一般"],
            "适用场景": "简单桌面应用、学习GUI编程"
        },
        "PyQt/PySide": {
            "优点": ["功能强大", "外观现代", "控件丰富", "性能优秀"],
            "缺点": ["体积较大", "学习复杂", "许可证限制"],
            "适用场景": "专业桌面应用、复杂界面"
        },
        "wxPython": {
            "优点": ["原生外观", "功能完整", "跨平台"],
            "缺点": ["API复杂", "文档较少", "更新较慢"],
            "适用场景": "需要原生外观的应用"
        },
        "Kivy": {
            "优点": ["现代设计", "触摸支持", "移动端支持"],
            "缺点": ["学习曲线陡", "桌面体验一般"],
            "适用场景": "移动应用、触摸界面"
        }
    }
    
    for framework, details in frameworks.items():
        print(f"\n  {framework}:")
        print(f"    优点: {', '.join(details['优点'])}")
        print(f"    缺点: {', '.join(details['缺点'])}")
        print(f"    适用场景: {details['适用场景']}")
    
    # 4. GUI设计原则
    print("\n4. GUI设计原则:")
    
    design_principles = [
        "一致性: 保持界面元素的一致性",
        "简洁性: 避免界面过于复杂",
        "可用性: 确保用户能够轻松使用",
        "反馈性: 及时给用户操作反馈",
        "容错性: 处理用户的错误操作",
        "可访问性: 考虑不同用户的需求"
    ]
    
    for i, principle in enumerate(design_principles, 1):
        print(f"    {i}. {principle}")

# 运行GUI编程介绍
gui_programming_intro()

# 二、Tkinter基础

# 2.1 基本窗口和控件

import tkinter as tk
from tkinter import ttk

def tkinter_basics_demo():
    """Tkinter基础控件演示"""
    print("=== Tkinter基础控件演示 ===")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Tkinter基础演示")
    root.geometry("600x500")
    root.resizable(True, True)
    
    # 设置窗口图标(如果有的话)
    # root.iconbitmap('icon.ico')
    
    # 1. 标签控件
    print("\n1. 创建标签控件")
    
    # 普通标签
    label1 = tk.Label(root, text="欢迎使用Tkinter!", 
                     font=("Arial", 16, "bold"),
                     fg="blue", bg="lightgray")
    label1.pack(pady=10)
    
    # 多行标签
    label2 = tk.Label(root, 
                     text="这是一个多行标签\n可以显示多行文本\n支持换行符",
                     justify=tk.LEFT,
                     font=("宋体", 12))
    label2.pack(pady=5)
    
    # 2. 按钮控件
    print("\n2. 创建按钮控件")
    
    def button_click():
        print("    按钮被点击了!")
        messagebox.showinfo("提示", "按钮点击事件触发!")
    
    def button_hover_enter(event):
        event.widget.config(bg="lightblue")
    
    def button_hover_leave(event):
        event.widget.config(bg="SystemButtonFace")
    
    button1 = tk.Button(root, text="点击我", 
                       command=button_click,
                       font=("Arial", 12),
                       width=15, height=2)
    button1.pack(pady=5)
    
    # 绑定鼠标悬停事件
    button1.bind("<Enter>", button_hover_enter)
    button1.bind("<Leave>", button_hover_leave)
    
    # 3. 文本输入控件
    print("\n3. 创建文本输入控件")
    
    # 单行文本框
    tk.Label(root, text="请输入您的姓名:").pack()
    entry_var = tk.StringVar()
    entry = tk.Entry(root, textvariable=entry_var, 
                    font=("Arial", 12), width=30)
    entry.pack(pady=5)
    
    def get_entry_text():
        text = entry_var.get()
        print(f"    输入的文本: {text}")
        if text:
            messagebox.showinfo("输入内容", f"您输入的是: {text}")
        else:
            messagebox.showwarning("警告", "请先输入内容!")
    
    tk.Button(root, text="获取输入", command=get_entry_text).pack(pady=5)
    
    # 4. 多行文本框
    print("\n4. 创建多行文本框")
    
    tk.Label(root, text="多行文本输入:").pack()
    
    # 创建文本框和滚动条的框架
    text_frame = tk.Frame(root)
    text_frame.pack(pady=5, padx=20, fill=tk.BOTH, expand=True)
    
    # 多行文本框
    text_widget = tk.Text(text_frame, height=8, width=50,
                         font=("Consolas", 10),
                         wrap=tk.WORD)
    
    # 滚动条
    scrollbar = tk.Scrollbar(text_frame)
    scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    
    text_widget.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    
    # 连接文本框和滚动条
    text_widget.config(yscrollcommand=scrollbar.set)
    scrollbar.config(command=text_widget.yview)
    
    # 插入默认文本
    default_text = """这是一个多行文本框示例。
您可以在这里输入多行文本。
支持滚动条和自动换行。

试试输入一些内容吧!"""
    text_widget.insert(tk.END, default_text)
    
    def get_text_content():
        content = text_widget.get("1.0", tk.END)
        print(f"    文本框内容: {repr(content)}")
        lines = content.strip().split('\n')
        messagebox.showinfo("文本内容", f"共 {len(lines)} 行,{len(content.strip())} 个字符")
    
    def clear_text():
        text_widget.delete("1.0", tk.END)
        print("    文本框已清空")
    
    # 文本操作按钮
    button_frame = tk.Frame(root)
    button_frame.pack(pady=5)
    
    tk.Button(button_frame, text="获取内容", 
             command=get_text_content).pack(side=tk.LEFT, padx=5)
    tk.Button(button_frame, text="清空内容", 
             command=clear_text).pack(side=tk.LEFT, padx=5)
    
    # 5. 复选框和单选按钮
    print("\n5. 创建复选框和单选按钮")
    
    # 复选框
    check_frame = tk.LabelFrame(root, text="兴趣爱好", padx=10, pady=10)
    check_frame.pack(pady=10, padx=20, fill=tk.X)
    
    hobbies = ["编程", "阅读", "音乐", "运动", "旅游"]
    hobby_vars = {}
    
    for hobby in hobbies:
        var = tk.BooleanVar()
        hobby_vars[hobby] = var
        cb = tk.Checkbutton(check_frame, text=hobby, variable=var)
        cb.pack(side=tk.LEFT, padx=5)
    
    def show_selected_hobbies():
        selected = [hobby for hobby, var in hobby_vars.items() if var.get()]
        if selected:
            messagebox.showinfo("选择的爱好", f"您选择了: {', '.join(selected)}")
        else:
            messagebox.showinfo("选择的爱好", "您没有选择任何爱好")
    
    tk.Button(check_frame, text="查看选择", 
             command=show_selected_hobbies).pack(side=tk.RIGHT, padx=5)
    
    # 单选按钮
    radio_frame = tk.LabelFrame(root, text="选择性别", padx=10, pady=10)
    radio_frame.pack(pady=5, padx=20, fill=tk.X)
    
    gender_var = tk.StringVar(value="男")
    genders = [("男", "male"), ("女", "female"), ("其他", "other")]
    
    for text, value in genders:
        rb = tk.Radiobutton(radio_frame, text=text, 
                           variable=gender_var, value=value)
        rb.pack(side=tk.LEFT, padx=10)
    
    def show_selected_gender():
        selected = gender_var.get()
        messagebox.showinfo("选择的性别", f"您选择了: {selected}")
    
    tk.Button(radio_frame, text="查看选择", 
             command=show_selected_gender).pack(side=tk.RIGHT, padx=5)
    
    # 窗口关闭事件
    def on_closing():
        if messagebox.askokcancel("退出", "确定要退出程序吗?"):
            print("\n程序正在退出...")
            root.destroy()
    
    root.protocol("WM_DELETE_WINDOW", on_closing)
    
    print("\n基础控件演示窗口已创建,请查看GUI界面")
    print("关闭窗口以继续下一个演示")
    
    # 启动事件循环
    root.mainloop()

# 运行Tkinter基础演示
tkinter_basics_demo()

# 2.2 布局管理

import tkinter as tk
from tkinter import ttk

def layout_management_demo():
    """布局管理演示"""
    print("=== 布局管理演示 ===")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("布局管理演示")
    root.geometry("800x600")
    
    # 创建笔记本控件来展示不同的布局方式
    notebook = ttk.Notebook(root)
    notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
    
    # 1. Pack布局演示
    print("\n1. Pack布局管理器")
    
    pack_frame = tk.Frame(notebook)
    notebook.add(pack_frame, text="Pack布局")
    
    # Pack布局说明
    tk.Label(pack_frame, text="Pack布局管理器", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    tk.Label(pack_frame, 
            text="Pack按照添加顺序依次排列控件,支持top、bottom、left、right四个方向",
            wraplength=400).pack(pady=5)
    
    # Pack示例
    pack_demo_frame = tk.LabelFrame(pack_frame, text="Pack示例", padx=10, pady=10)
    pack_demo_frame.pack(pady=10, padx=20, fill=tk.X)
    
    tk.Button(pack_demo_frame, text="Top 1", bg="lightblue").pack(side=tk.TOP, pady=2)
    tk.Button(pack_demo_frame, text="Top 2", bg="lightgreen").pack(side=tk.TOP, pady=2)
    
    bottom_frame = tk.Frame(pack_demo_frame)
    bottom_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=5)
    tk.Button(bottom_frame, text="Bottom 1", bg="lightcoral").pack(side=tk.LEFT, padx=2)
    tk.Button(bottom_frame, text="Bottom 2", bg="lightyellow").pack(side=tk.RIGHT, padx=2)
    
    middle_frame = tk.Frame(pack_demo_frame)
    middle_frame.pack(fill=tk.BOTH, expand=True, pady=5)
    tk.Button(middle_frame, text="Left", bg="lightpink").pack(side=tk.LEFT, padx=2)
    tk.Button(middle_frame, text="Right", bg="lightgray").pack(side=tk.RIGHT, padx=2)
    tk.Label(middle_frame, text="Center Area", bg="white", 
            relief=tk.SUNKEN).pack(fill=tk.BOTH, expand=True, padx=5)
    
    # 2. Grid布局演示
    print("\n2. Grid布局管理器")
    
    grid_frame = tk.Frame(notebook)
    notebook.add(grid_frame, text="Grid布局")
    
    tk.Label(grid_frame, text="Grid布局管理器", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    tk.Label(grid_frame, 
            text="Grid使用行列网格来精确控制控件位置,适合复杂布局",
            wraplength=400).pack(pady=5)
    
    # Grid示例 - 计算器布局
    grid_demo_frame = tk.LabelFrame(grid_frame, text="Grid示例 - 计算器布局", 
                                   padx=10, pady=10)
    grid_demo_frame.pack(pady=10, padx=20)
    
    # 显示屏
    display = tk.Entry(grid_demo_frame, width=20, font=("Arial", 14), 
                      justify=tk.RIGHT, state="readonly")
    display.grid(row=0, column=0, columnspan=4, padx=5, pady=5, sticky="ew")
    
    # 按钮布局
    buttons = [
        ['C', '±', '%', '÷'],
        ['7', '8', '9', '×'],
        ['4', '5', '6', '-'],
        ['1', '2', '3', '+'],
        ['0', '', '.', '=']
    ]
    
    for i, row in enumerate(buttons, 1):
        for j, text in enumerate(row):
            if text:  # 跳过空按钮
                if text == '0':
                    # 0按钮占两列
                    btn = tk.Button(grid_demo_frame, text=text, width=5, height=2)
                    btn.grid(row=i, column=j, columnspan=2, padx=2, pady=2, sticky="ew")
                elif text in ['÷', '×', '-', '+', '=']:
                    # 运算符按钮
                    btn = tk.Button(grid_demo_frame, text=text, width=5, height=2, 
                                   bg="orange", fg="white")
                    btn.grid(row=i, column=j, padx=2, pady=2, sticky="ew")
                elif text in ['C', '±', '%']:
                    # 功能按钮
                    btn = tk.Button(grid_demo_frame, text=text, width=5, height=2, 
                                   bg="lightgray")
                    btn.grid(row=i, column=j, padx=2, pady=2, sticky="ew")
                else:
                    # 数字按钮
                    btn = tk.Button(grid_demo_frame, text=text, width=5, height=2)
                    btn.grid(row=i, column=j, padx=2, pady=2, sticky="ew")
    
    # 3. Place布局演示
    print("\n3. Place布局管理器")
    
    place_frame = tk.Frame(notebook)
    notebook.add(place_frame, text="Place布局")
    
    tk.Label(place_frame, text="Place布局管理器", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    tk.Label(place_frame, 
            text="Place使用绝对或相对坐标精确定位控件,适合特殊布局需求",
            wraplength=400).pack(pady=5)
    
    # Place示例
    place_demo_frame = tk.LabelFrame(place_frame, text="Place示例", 
                                    width=400, height=300)
    place_demo_frame.pack(pady=10, padx=20)
    place_demo_frame.pack_propagate(False)  # 防止框架自动调整大小
    
    # 绝对定位
    tk.Button(place_demo_frame, text="绝对定位(10,10)", bg="lightblue").place(x=10, y=10)
    tk.Button(place_demo_frame, text="绝对定位(200,50)", bg="lightgreen").place(x=200, y=50)
    
    # 相对定位
    tk.Button(place_demo_frame, text="相对定位(50%,30%)", 
             bg="lightcoral").place(relx=0.5, rely=0.3, anchor=tk.CENTER)
    
    tk.Button(place_demo_frame, text="右下角", 
             bg="lightyellow").place(relx=1.0, rely=1.0, anchor=tk.SE, x=-10, y=-10)
    
    # 大小控制
    tk.Label(place_demo_frame, text="相对大小控制", bg="lightpink", 
            relief=tk.RAISED).place(relx=0.1, rely=0.6, relwidth=0.8, relheight=0.2)
    
    # 4. 混合布局演示
    print("\n4. 混合布局管理器")
    
    mixed_frame = tk.Frame(notebook)
    notebook.add(mixed_frame, text="混合布局")
    
    tk.Label(mixed_frame, text="混合布局管理器", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    tk.Label(mixed_frame, 
            text="在不同的容器中可以使用不同的布局管理器,实现复杂界面",
            wraplength=400).pack(pady=5)
    
    # 混合布局示例 - 文本编辑器界面
    mixed_demo_frame = tk.Frame(mixed_frame)
    mixed_demo_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
    
    # 顶部工具栏 - 使用Pack
    toolbar = tk.Frame(mixed_demo_frame, bg="lightgray", height=40)
    toolbar.pack(fill=tk.X, pady=(0, 5))
    toolbar.pack_propagate(False)
    
    tk.Button(toolbar, text="新建").pack(side=tk.LEFT, padx=5, pady=5)
    tk.Button(toolbar, text="打开").pack(side=tk.LEFT, padx=5, pady=5)
    tk.Button(toolbar, text="保存").pack(side=tk.LEFT, padx=5, pady=5)
    
    ttk.Separator(toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.Y, padx=5)
    
    tk.Button(toolbar, text="复制").pack(side=tk.LEFT, padx=5, pady=5)
    tk.Button(toolbar, text="粘贴").pack(side=tk.LEFT, padx=5, pady=5)
    
    # 主要内容区域 - 使用Grid
    content_frame = tk.Frame(mixed_demo_frame)
    content_frame.pack(fill=tk.BOTH, expand=True)
    
    # 配置Grid权重
    content_frame.grid_rowconfigure(0, weight=1)
    content_frame.grid_columnconfigure(1, weight=1)
    
    # 左侧文件树
    tree_frame = tk.LabelFrame(content_frame, text="文件", width=150)
    tree_frame.grid(row=0, column=0, sticky="nsew", padx=(0, 5))
    tree_frame.grid_propagate(False)
    
    file_list = tk.Listbox(tree_frame)
    file_list.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
    for i in range(1, 6):
        file_list.insert(tk.END, f"文件{i}.txt")
    
    # 右侧编辑区域
    edit_frame = tk.LabelFrame(content_frame, text="编辑器")
    edit_frame.grid(row=0, column=1, sticky="nsew")
    
    edit_text = tk.Text(edit_frame, wrap=tk.WORD)
    edit_scrollbar = tk.Scrollbar(edit_frame)
    
    edit_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(5, 0), pady=5)
    edit_scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=5, padx=(0, 5))
    
    edit_text.config(yscrollcommand=edit_scrollbar.set)
    edit_scrollbar.config(command=edit_text.yview)
    
    # 底部状态栏 - 使用Pack
    status_bar = tk.Frame(mixed_demo_frame, bg="lightgray", height=25)
    status_bar.pack(fill=tk.X, pady=(5, 0))
    status_bar.pack_propagate(False)
    
    tk.Label(status_bar, text="就绪", bg="lightgray").pack(side=tk.LEFT, padx=5)
    tk.Label(status_bar, text="行: 1, 列: 1", bg="lightgray").pack(side=tk.RIGHT, padx=5)
    
    print("\n布局管理演示窗口已创建,请查看GUI界面")
    print("关闭窗口以继续下一个演示")
    
    # 启动事件循环
    root.mainloop()

# 运行布局管理演示
layout_management_demo()

# 三、事件处理

# 3.1 事件绑定和处理

import tkinter as tk
from tkinter import messagebox
import time

def event_handling_demo():
    """事件处理演示"""
    print("=== 事件处理演示 ===")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("事件处理演示")
    root.geometry("700x600")
    
    # 事件日志显示区域
    log_frame = tk.LabelFrame(root, text="事件日志", padx=5, pady=5)
    log_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
    
    log_text = tk.Text(log_frame, height=15, font=("Consolas", 10))
    log_scrollbar = tk.Scrollbar(log_frame)
    
    log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    
    log_text.config(yscrollcommand=log_scrollbar.set)
    log_scrollbar.config(command=log_text.yview)
    
    def log_event(message):
        """记录事件到日志"""
        timestamp = time.strftime("%H:%M:%S")
        log_text.insert(tk.END, f"[{timestamp}] {message}\n")
        log_text.see(tk.END)
        print(f"    事件: {message}")
    
    def clear_log():
        """清空日志"""
        log_text.delete("1.0", tk.END)
        log_event("日志已清空")
    
    # 1. 鼠标事件
    print("\n1. 鼠标事件处理")
    
    mouse_frame = tk.LabelFrame(root, text="鼠标事件测试区域", padx=10, pady=10)
    mouse_frame.pack(fill=tk.X, padx=10, pady=5)
    
    mouse_label = tk.Label(mouse_frame, text="鼠标事件测试区域", 
                          bg="lightblue", width=30, height=3,
                          relief=tk.RAISED, cursor="hand2")
    mouse_label.pack(pady=5)
    
    # 鼠标事件处理函数
    def on_mouse_click(event):
        log_event(f"鼠标点击: 按钮{event.num}, 坐标({event.x}, {event.y})")
    
    def on_mouse_double_click(event):
        log_event(f"鼠标双击: 坐标({event.x}, {event.y})")
        mouse_label.config(bg="lightgreen")
        root.after(500, lambda: mouse_label.config(bg="lightblue"))
    
    def on_mouse_enter(event):
        log_event("鼠标进入区域")
        mouse_label.config(relief=tk.SUNKEN)
    
    def on_mouse_leave(event):
        log_event("鼠标离开区域")
        mouse_label.config(relief=tk.RAISED)
    
    def on_mouse_motion(event):
        # 只记录每10个像素的移动,避免日志过多
        if event.x % 10 == 0 and event.y % 10 == 0:
            log_event(f"鼠标移动: 坐标({event.x}, {event.y})")
    
    # 绑定鼠标事件
    mouse_label.bind("<Button-1>", on_mouse_click)  # 左键点击
    mouse_label.bind("<Button-3>", on_mouse_click)  # 右键点击
    mouse_label.bind("<Double-Button-1>", on_mouse_double_click)  # 双击
    mouse_label.bind("<Enter>", on_mouse_enter)  # 鼠标进入
    mouse_label.bind("<Leave>", on_mouse_leave)  # 鼠标离开
    mouse_label.bind("<Motion>", on_mouse_motion)  # 鼠标移动
    
    # 2. 键盘事件
    print("\n2. 键盘事件处理")
    
    keyboard_frame = tk.LabelFrame(root, text="键盘事件测试", padx=10, pady=10)
    keyboard_frame.pack(fill=tk.X, padx=10, pady=5)
    
    tk.Label(keyboard_frame, text="点击下面的输入框并输入内容:").pack()
    
    keyboard_entry = tk.Entry(keyboard_frame, font=("Arial", 12), width=40)
    keyboard_entry.pack(pady=5)
    keyboard_entry.focus_set()  # 设置焦点
    
    # 键盘事件处理函数
    def on_key_press(event):
        key_info = f"按键按下: '{event.char}' (键码: {event.keycode})"
        if event.char.isprintable():
            log_event(key_info)
        elif event.keysym in ['Return', 'BackSpace', 'Delete', 'Tab']:
            log_event(f"特殊键按下: {event.keysym}")
    
    def on_key_release(event):
        if event.keysym == 'Return':
            content = keyboard_entry.get()
            log_event(f"回车键释放,当前内容: '{content}'")
    
    def on_focus_in(event):
        log_event("输入框获得焦点")
        keyboard_entry.config(bg="lightyellow")
    
    def on_focus_out(event):
        log_event("输入框失去焦点")
        keyboard_entry.config(bg="white")
    
    # 绑定键盘事件
    keyboard_entry.bind("<KeyPress>", on_key_press)
    keyboard_entry.bind("<KeyRelease>", on_key_release)
    keyboard_entry.bind("<FocusIn>", on_focus_in)
    keyboard_entry.bind("<FocusOut>", on_focus_out)
    
    # 3. 窗口事件
    print("\n3. 窗口事件处理")
    
    def on_window_resize(event):
        if event.widget == root:  # 只处理主窗口的调整事件
            log_event(f"窗口大小调整: {event.width}x{event.height}")
    
    def on_window_focus_in(event):
        if event.widget == root:
            log_event("窗口获得焦点")
    
    def on_window_focus_out(event):
        if event.widget == root:
            log_event("窗口失去焦点")
    
    # 绑定窗口事件
    root.bind("<Configure>", on_window_resize)
    root.bind("<FocusIn>", on_window_focus_in)
    root.bind("<FocusOut>", on_window_focus_out)
    
    # 4. 自定义事件
    print("\n4. 自定义事件处理")
    
    custom_frame = tk.LabelFrame(root, text="自定义事件", padx=10, pady=10)
    custom_frame.pack(fill=tk.X, padx=10, pady=5)
    
    # 自定义事件处理函数
    def trigger_custom_event():
        # 生成自定义事件
        root.event_generate("<<CustomEvent>>", when="tail")
        log_event("触发自定义事件")
    
    def on_custom_event(event):
        log_event("处理自定义事件")
        messagebox.showinfo("自定义事件", "自定义事件被触发了!")
    
    # 绑定自定义事件
    root.bind("<<CustomEvent>>", on_custom_event)
    
    tk.Button(custom_frame, text="触发自定义事件", 
             command=trigger_custom_event).pack(side=tk.LEFT, padx=5)
    
    # 5. 定时器事件
    print("\n5. 定时器事件处理")
    
    timer_running = False
    timer_count = 0
    
    def timer_callback():
        global timer_count
        if timer_running:
            timer_count += 1
            log_event(f"定时器事件: 第{timer_count}次")
            # 每秒触发一次
            root.after(1000, timer_callback)
    
    def start_timer():
        global timer_running, timer_count
        if not timer_running:
            timer_running = True
            timer_count = 0
            log_event("启动定时器")
            timer_callback()
    
    def stop_timer():
        global timer_running
        if timer_running:
            timer_running = False
            log_event("停止定时器")
    
    tk.Button(custom_frame, text="启动定时器", 
             command=start_timer).pack(side=tk.LEFT, padx=5)
    tk.Button(custom_frame, text="停止定时器", 
             command=stop_timer).pack(side=tk.LEFT, padx=5)
    
    # 控制按钮
    control_frame = tk.Frame(root)
    control_frame.pack(fill=tk.X, padx=10, pady=5)
    
    tk.Button(control_frame, text="清空日志", 
             command=clear_log).pack(side=tk.LEFT, padx=5)
    
    def show_help():
        help_text = """事件处理演示说明:

1. 鼠标事件: 在蓝色区域进行鼠标操作
2. 键盘事件: 在输入框中输入内容
3. 窗口事件: 调整窗口大小或切换焦点
4. 自定义事件: 点击按钮触发
5. 定时器事件: 启动/停止定时器

所有事件都会记录在日志中。"""
        messagebox.showinfo("帮助", help_text)
    
    tk.Button(control_frame, text="帮助", 
             command=show_help).pack(side=tk.RIGHT, padx=5)
    
    # 初始化日志
    log_event("事件处理演示程序启动")
    
    print("\n事件处理演示窗口已创建,请查看GUI界面")
    print("尝试各种操作来触发不同的事件")
    print("关闭窗口以继续下一个演示")
    
    # 窗口关闭事件
    def on_closing():
        stop_timer()  # 停止定时器
        log_event("程序即将退出")
        root.destroy()
    
    root.protocol("WM_DELETE_WINDOW", on_closing)
    
    # 启动事件循环
    root.mainloop()

# 运行事件处理演示
event_handling_demo()

# 四、高级控件

# 4.1 菜单和对话框

import tkinter as tk
from tkinter import ttk, messagebox, filedialog, colorchooser, simpledialog
import os

def advanced_widgets_demo():
    """高级控件演示"""
    print("=== 高级控件演示 ===")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("高级控件演示")
    root.geometry("800x600")
    
    # 状态变量
    current_file = None
    
    # 1. 菜单栏
    print("\n1. 创建菜单栏")
    
    menubar = tk.Menu(root)
    root.config(menu=menubar)
    
    # 文件菜单
    file_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="文件", menu=file_menu)
    
    def new_file():
        global current_file
        if messagebox.askyesno("新建文件", "确定要新建文件吗?未保存的内容将丢失。"):
            text_area.delete("1.0", tk.END)
            current_file = None
            root.title("高级控件演示 - 新文件")
            status_var.set("新建文件")
    
    def open_file():
        global current_file
        filename = filedialog.askopenfilename(
            title="打开文件",
            filetypes=[("文本文件", "*.txt"), ("Python文件", "*.py"), ("所有文件", "*.*")]
        )
        if filename:
            try:
                with open(filename, 'r', encoding='utf-8') as file:
                    content = file.read()
                    text_area.delete("1.0", tk.END)
                    text_area.insert("1.0", content)
                    current_file = filename
                    root.title(f"高级控件演示 - {os.path.basename(filename)}")
                    status_var.set(f"已打开: {filename}")
            except Exception as e:
                messagebox.showerror("错误", f"无法打开文件: {e}")
    
    def save_file():
        global current_file
        if current_file:
            try:
                content = text_area.get("1.0", tk.END)
                with open(current_file, 'w', encoding='utf-8') as file:
                    file.write(content)
                status_var.set(f"已保存: {current_file}")
            except Exception as e:
                messagebox.showerror("错误", f"无法保存文件: {e}")
        else:
            save_as_file()
    
    def save_as_file():
        global current_file
        filename = filedialog.asksaveasfilename(
            title="另存为",
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("Python文件", "*.py"), ("所有文件", "*.*")]
        )
        if filename:
            try:
                content = text_area.get("1.0", tk.END)
                with open(filename, 'w', encoding='utf-8') as file:
                    file.write(content)
                current_file = filename
                root.title(f"高级控件演示 - {os.path.basename(filename)}")
                status_var.set(f"已保存为: {filename}")
            except Exception as e:
                messagebox.showerror("错误", f"无法保存文件: {e}")
    
    def exit_app():
        if messagebox.askyesno("退出", "确定要退出程序吗?"):
            root.destroy()
    
    file_menu.add_command(label="新建", command=new_file, accelerator="Ctrl+N")
    file_menu.add_command(label="打开", command=open_file, accelerator="Ctrl+O")
    file_menu.add_separator()
    file_menu.add_command(label="保存", command=save_file, accelerator="Ctrl+S")
    file_menu.add_command(label="另存为", command=save_as_file, accelerator="Ctrl+Shift+S")
    file_menu.add_separator()
    file_menu.add_command(label="退出", command=exit_app, accelerator="Ctrl+Q")
    
    # 编辑菜单
    edit_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="编辑", menu=edit_menu)
    
    def undo():
        try:
            text_area.edit_undo()
        except tk.TclError:
            pass
    
    def redo():
        try:
            text_area.edit_redo()
        except tk.TclError:
            pass
    
    def cut():
        try:
            text_area.event_generate("<<Cut>>")
        except tk.TclError:
            pass
    
    def copy():
        try:
            text_area.event_generate("<<Copy>>")
        except tk.TclError:
            pass
    
    def paste():
        try:
            text_area.event_generate("<<Paste>>")
        except tk.TclError:
            pass
    
    def select_all():
        text_area.tag_add(tk.SEL, "1.0", tk.END)
        text_area.mark_set(tk.INSERT, "1.0")
        text_area.see(tk.INSERT)
    
    edit_menu.add_command(label="撤销", command=undo, accelerator="Ctrl+Z")
    edit_menu.add_command(label="重做", command=redo, accelerator="Ctrl+Y")
    edit_menu.add_separator()
    edit_menu.add_command(label="剪切", command=cut, accelerator="Ctrl+X")
    edit_menu.add_command(label="复制", command=copy, accelerator="Ctrl+C")
    edit_menu.add_command(label="粘贴", command=paste, accelerator="Ctrl+V")
    edit_menu.add_separator()
    edit_menu.add_command(label="全选", command=select_all, accelerator="Ctrl+A")
    
    # 格式菜单
    format_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="格式", menu=format_menu)
    
    def change_font():
        # 简单的字体选择对话框
        font_families = ['Arial', 'Times New Roman', 'Courier New', '宋体', '微软雅黑']
        font_sizes = ['8', '10', '12', '14', '16', '18', '20', '24']
        
        font_window = tk.Toplevel(root)
        font_window.title("字体设置")
        font_window.geometry("400x300")
        font_window.transient(root)
        font_window.grab_set()
        
        tk.Label(font_window, text="字体:").grid(row=0, column=0, sticky="w", padx=10, pady=5)
        font_var = tk.StringVar(value="Arial")
        font_combo = ttk.Combobox(font_window, textvariable=font_var, values=font_families)
        font_combo.grid(row=0, column=1, padx=10, pady=5)
        
        tk.Label(font_window, text="大小:").grid(row=1, column=0, sticky="w", padx=10, pady=5)
        size_var = tk.StringVar(value="12")
        size_combo = ttk.Combobox(font_window, textvariable=size_var, values=font_sizes)
        size_combo.grid(row=1, column=1, padx=10, pady=5)
        
        def apply_font():
            font_family = font_var.get()
            font_size = int(size_var.get())
            text_area.config(font=(font_family, font_size))
            font_window.destroy()
        
        tk.Button(font_window, text="确定", command=apply_font).grid(row=2, column=0, columnspan=2, pady=20)
    
    def change_color():
        color = colorchooser.askcolor(title="选择文字颜色")
        if color[1]:  # 如果选择了颜色
            text_area.config(fg=color[1])
    
    def change_bg_color():
        color = colorchooser.askcolor(title="选择背景颜色")
        if color[1]:  # 如果选择了颜色
            text_area.config(bg=color[1])
    
    format_menu.add_command(label="字体", command=change_font)
    format_menu.add_command(label="文字颜色", command=change_color)
    format_menu.add_command(label="背景颜色", command=change_bg_color)
    
    # 帮助菜单
    help_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="帮助", menu=help_menu)
    
    def show_about():
        messagebox.showinfo("关于", "高级控件演示程序\n\n版本: 1.0\n作者: Python学习者")
    
    help_menu.add_command(label="关于", command=show_about)
    
    # 2. 工具栏
    print("\n2. 创建工具栏")
    
    toolbar = tk.Frame(root, bg="lightgray", height=40)
    toolbar.pack(fill=tk.X)
    toolbar.pack_propagate(False)
    
    # 工具栏按钮
    tk.Button(toolbar, text="新建", command=new_file, relief=tk.FLAT).pack(side=tk.LEFT, padx=2, pady=2)
    tk.Button(toolbar, text="打开", command=open_file, relief=tk.FLAT).pack(side=tk.LEFT, padx=2, pady=2)
    tk.Button(toolbar, text="保存", command=save_file, relief=tk.FLAT).pack(side=tk.LEFT, padx=2, pady=2)
    
    ttk.Separator(toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.Y, padx=5)
    
    tk.Button(toolbar, text="剪切", command=cut, relief=tk.FLAT).pack(side=tk.LEFT, padx=2, pady=2)
    tk.Button(toolbar, text="复制", command=copy, relief=tk.FLAT).pack(side=tk.LEFT, padx=2, pady=2)
    tk.Button(toolbar, text="粘贴", command=paste, relief=tk.FLAT).pack(side=tk.LEFT, padx=2, pady=2)
    
    # 3. 主要内容区域
    print("\n3. 创建主要内容区域")
    
    # 创建文本编辑区域
    text_frame = tk.Frame(root)
    text_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
    
    text_area = tk.Text(text_frame, wrap=tk.WORD, undo=True, font=("Consolas", 12))
    text_scrollbar_y = tk.Scrollbar(text_frame, orient=tk.VERTICAL)
    text_scrollbar_x = tk.Scrollbar(text_frame, orient=tk.HORIZONTAL)
    
    text_area.grid(row=0, column=0, sticky="nsew")
    text_scrollbar_y.grid(row=0, column=1, sticky="ns")
    text_scrollbar_x.grid(row=1, column=0, sticky="ew")
    
    text_frame.grid_rowconfigure(0, weight=1)
    text_frame.grid_columnconfigure(0, weight=1)
    
    text_area.config(yscrollcommand=text_scrollbar_y.set, xscrollcommand=text_scrollbar_x.set)
    text_scrollbar_y.config(command=text_area.yview)
    text_scrollbar_x.config(command=text_area.xview)
    
    # 插入示例文本
    sample_text = """欢迎使用高级控件演示程序!

这是一个功能完整的文本编辑器示例,包含以下功能:

1. 完整的菜单栏
   - 文件操作:新建、打开、保存、另存为
   - 编辑操作:撤销、重做、剪切、复制、粘贴、全选
   - 格式设置:字体、颜色
   - 帮助信息

2. 工具栏快捷按钮

3. 文本编辑区域
   - 支持撤销/重做
   - 支持滚动条
   - 支持自动换行

4. 状态栏显示

试试使用菜单和工具栏的各种功能吧!"""
    
    text_area.insert("1.0", sample_text)
    
    # 4. 状态栏
    print("\n4. 创建状态栏")
    
    status_frame = tk.Frame(root, bg="lightgray", height=25)
    status_frame.pack(fill=tk.X)
    status_frame.pack_propagate(False)
    
    status_var = tk.StringVar(value="就绪")
    status_label = tk.Label(status_frame, textvariable=status_var, bg="lightgray")
    status_label.pack(side=tk.LEFT, padx=5)
    
    # 显示光标位置
    cursor_var = tk.StringVar(value="行: 1, 列: 1")
    cursor_label = tk.Label(status_frame, textvariable=cursor_var, bg="lightgray")
    cursor_label.pack(side=tk.RIGHT, padx=5)
    
    def update_cursor_position(event=None):
        cursor_pos = text_area.index(tk.INSERT)
        line, col = cursor_pos.split('.')
        cursor_var.set(f"行: {line}, 列: {int(col)+1}")
    
    text_area.bind("<KeyRelease>", update_cursor_position)
    text_area.bind("<ButtonRelease>", update_cursor_position)
    
    # 5. 键盘快捷键
    print("\n5. 绑定键盘快捷键")
    
    root.bind("<Control-n>", lambda e: new_file())
    root.bind("<Control-o>", lambda e: open_file())
    root.bind("<Control-s>", lambda e: save_file())
    root.bind("<Control-Shift-S>", lambda e: save_as_file())
    root.bind("<Control-q>", lambda e: exit_app())
    root.bind("<Control-z>", lambda e: undo())
    root.bind("<Control-y>", lambda e: redo())
    root.bind("<Control-a>", lambda e: select_all())
    
    # 6. 右键菜单
    print("\n6. 创建右键菜单")
    
    context_menu = tk.Menu(root, tearoff=0)
    context_menu.add_command(label="剪切", command=cut)
    context_menu.add_command(label="复制", command=copy)
    context_menu.add_command(label="粘贴", command=paste)
    context_menu.add_separator()
    context_menu.add_command(label="全选", command=select_all)
    
    def show_context_menu(event):
        try:
            context_menu.tk_popup(event.x_root, event.y_root)
        finally:
            context_menu.grab_release()
    
    text_area.bind("<Button-3>", show_context_menu)  # 右键点击
    
    print("\n高级控件演示窗口已创建,请查看GUI界面")
    print("尝试使用菜单、工具栏和各种功能")
    print("关闭窗口以继续下一个演示")
    
    # 启动事件循环
    root.mainloop()

# 运行高级控件演示
advanced_widgets_demo()

# 4.2 列表和树形控件

import tkinter as tk
from tkinter import ttk, messagebox
import random
import datetime

def list_tree_demo():
    """列表和树形控件演示"""
    print("=== 列表和树形控件演示 ===")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("列表和树形控件演示")
    root.geometry("900x700")
    
    # 创建笔记本控件
    notebook = ttk.Notebook(root)
    notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
    
    # 1. 列表框演示
    print("\n1. 列表框控件演示")
    
    listbox_frame = tk.Frame(notebook)
    notebook.add(listbox_frame, text="列表框")
    
    tk.Label(listbox_frame, text="列表框控件演示", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    # 创建列表框区域
    list_container = tk.Frame(listbox_frame)
    list_container.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
    
    # 左侧 - 单选列表框
    left_frame = tk.LabelFrame(list_container, text="单选列表框", padx=10, pady=10)
    left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))
    
    single_listbox = tk.Listbox(left_frame, selectmode=tk.SINGLE, height=10)
    single_scrollbar = tk.Scrollbar(left_frame, orient=tk.VERTICAL)
    
    single_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    single_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    
    single_listbox.config(yscrollcommand=single_scrollbar.set)
    single_scrollbar.config(command=single_listbox.yview)
    
    # 添加示例数据
    cities = ["北京", "上海", "广州", "深圳", "杭州", "南京", "武汉", "成都", "西安", "重庆"]
    for city in cities:
        single_listbox.insert(tk.END, city)
    
    def on_single_select(event):
        selection = single_listbox.curselection()
        if selection:
            selected_city = single_listbox.get(selection[0])
            messagebox.showinfo("选择", f"您选择了: {selected_city}")
    
    single_listbox.bind("<<ListboxSelect>>", on_single_select)
    
    # 右侧 - 多选列表框
    right_frame = tk.LabelFrame(list_container, text="多选列表框", padx=10, pady=10)
    right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(10, 0))
    
    multi_listbox = tk.Listbox(right_frame, selectmode=tk.MULTIPLE, height=10)
    multi_scrollbar = tk.Scrollbar(right_frame, orient=tk.VERTICAL)
    
    multi_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    multi_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    
    multi_listbox.config(yscrollcommand=multi_scrollbar.set)
    multi_scrollbar.config(command=multi_listbox.yview)
    
    # 添加示例数据
    languages = ["Python", "Java", "C++", "JavaScript", "Go", "Rust", "Swift", "Kotlin", "C#", "PHP"]
    for lang in languages:
        multi_listbox.insert(tk.END, lang)
    
    def show_multi_selection():
        selections = multi_listbox.curselection()
        if selections:
            selected_langs = [multi_listbox.get(i) for i in selections]
            messagebox.showinfo("多选结果", f"您选择了: {', '.join(selected_langs)}")
        else:
            messagebox.showinfo("多选结果", "没有选择任何项目")
    
    tk.Button(right_frame, text="查看选择", command=show_multi_selection).pack(pady=5)
    
    # 2. 树形控件演示
    print("\n2. 树形控件演示")
    
    tree_frame = tk.Frame(notebook)
    notebook.add(tree_frame, text="树形控件")
    
    tk.Label(tree_frame, text="树形控件演示", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    # 创建树形控件
    tree_container = tk.Frame(tree_frame)
    tree_container.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
    
    # 定义列
    columns = ("name", "type", "size", "modified")
    tree = ttk.Treeview(tree_container, columns=columns, show="tree headings", height=15)
    
    # 配置列
    tree.heading("#0", text="文件/文件夹", anchor=tk.W)
    tree.heading("name", text="名称", anchor=tk.W)
    tree.heading("type", text="类型", anchor=tk.W)
    tree.heading("size", text="大小", anchor=tk.E)
    tree.heading("modified", text="修改时间", anchor=tk.W)
    
    tree.column("#0", width=200, minwidth=100)
    tree.column("name", width=150, minwidth=100)
    tree.column("type", width=100, minwidth=80)
    tree.column("size", width=100, minwidth=80)
    tree.column("modified", width=150, minwidth=120)
    
    # 添加滚动条
    tree_scrollbar_y = ttk.Scrollbar(tree_container, orient=tk.VERTICAL, command=tree.yview)
    tree_scrollbar_x = ttk.Scrollbar(tree_container, orient=tk.HORIZONTAL, command=tree.xview)
    tree.configure(yscrollcommand=tree_scrollbar_y.set, xscrollcommand=tree_scrollbar_x.set)
    
    tree.grid(row=0, column=0, sticky="nsew")
    tree_scrollbar_y.grid(row=0, column=1, sticky="ns")
    tree_scrollbar_x.grid(row=1, column=0, sticky="ew")
    
    tree_container.grid_rowconfigure(0, weight=1)
    tree_container.grid_columnconfigure(0, weight=1)
    
    # 添加示例数据
    def add_sample_data():
        # 根目录
        root_id = tree.insert("", "end", text="我的电脑", values=("", "文件夹", "", ""))
        
        # C盘
        c_drive = tree.insert(root_id, "end", text="C:\\", values=("C:\\", "磁盘", "500 GB", "2023-01-01"))
        
        # 程序文件夹
        program_files = tree.insert(c_drive, "end", text="Program Files", 
                                   values=("Program Files", "文件夹", "15 GB", "2023-06-01"))
        
        # Python文件夹
        python_folder = tree.insert(program_files, "end", text="Python", 
                                   values=("Python", "文件夹", "2 GB", "2023-06-15"))
        
        # Python文件
        tree.insert(python_folder, "end", text="python.exe", 
                   values=("python.exe", "应用程序", "25 MB", "2023-06-15"))
        tree.insert(python_folder, "end", text="pip.exe", 
                   values=("pip.exe", "应用程序", "5 MB", "2023-06-15"))
        
        # 用户文件夹
        users = tree.insert(c_drive, "end", text="Users", 
                           values=("Users", "文件夹", "50 GB", "2023-05-01"))
        
        user_folder = tree.insert(users, "end", text="用户", 
                                 values=("用户", "文件夹", "30 GB", "2023-06-01"))
        
        # 文档文件夹
        documents = tree.insert(user_folder, "end", text="Documents", 
                               values=("Documents", "文件夹", "10 GB", "2023-06-10"))
        
        # 示例文档
        tree.insert(documents, "end", text="report.docx", 
                   values=("report.docx", "Word文档", "2 MB", "2023-06-15"))
        tree.insert(documents, "end", text="data.xlsx", 
                   values=("data.xlsx", "Excel文档", "5 MB", "2023-06-14"))
        tree.insert(documents, "end", text="presentation.pptx", 
                   values=("presentation.pptx", "PowerPoint", "10 MB", "2023-06-13"))
        
        # D盘
        d_drive = tree.insert(root_id, "end", text="D:\\", values=("D:\\", "磁盘", "1 TB", "2023-01-01"))
        
        # 项目文件夹
        projects = tree.insert(d_drive, "end", text="Projects", 
                              values=("Projects", "文件夹", "20 GB", "2023-06-01"))
        
        python_project = tree.insert(projects, "end", text="PythonProject", 
                                    values=("PythonProject", "文件夹", "500 MB", "2023-06-15"))
        
        tree.insert(python_project, "end", text="main.py", 
                   values=("main.py", "Python文件", "10 KB", "2023-06-15"))
        tree.insert(python_project, "end", text="requirements.txt", 
                   values=("requirements.txt", "文本文件", "1 KB", "2023-06-10"))
        
        # 展开根节点
        tree.item(root_id, open=True)
        tree.item(c_drive, open=True)
    
    add_sample_data()
    
    # 树形控件事件处理
    def on_tree_select(event):
        selection = tree.selection()
        if selection:
            item = selection[0]
            item_text = tree.item(item, "text")
            item_values = tree.item(item, "values")
            print(f"    选择了: {item_text}, 值: {item_values}")
    
    def on_tree_double_click(event):
        selection = tree.selection()
        if selection:
            item = selection[0]
            item_text = tree.item(item, "text")
            messagebox.showinfo("双击", f"双击了: {item_text}")
    
    tree.bind("<<TreeviewSelect>>", on_tree_select)
    tree.bind("<Double-1>", on_tree_double_click)
    
    # 树形控件操作按钮
    tree_buttons = tk.Frame(tree_frame)
    tree_buttons.pack(fill=tk.X, padx=20, pady=5)
    
    def expand_all():
        def expand_item(item):
            tree.item(item, open=True)
            for child in tree.get_children(item):
                expand_item(child)
        
        for item in tree.get_children():
            expand_item(item)
    
    def collapse_all():
        def collapse_item(item):
            tree.item(item, open=False)
            for child in tree.get_children(item):
                collapse_item(child)
        
        for item in tree.get_children():
            collapse_item(item)
    
    def add_item():
        selection = tree.selection()
        if selection:
            parent = selection[0]
            new_item = f"新项目_{random.randint(1, 1000)}"
            tree.insert(parent, "end", text=new_item, 
                       values=(new_item, "文件", "1 KB", datetime.datetime.now().strftime("%Y-%m-%d")))
        else:
            messagebox.showwarning("警告", "请先选择一个父节点")
    
    def delete_item():
        selection = tree.selection()
        if selection:
            if messagebox.askyesno("确认", "确定要删除选中的项目吗?"):
                tree.delete(selection[0])
        else:
            messagebox.showwarning("警告", "请先选择要删除的项目")
    
    tk.Button(tree_buttons, text="展开全部", command=expand_all).pack(side=tk.LEFT, padx=5)
    tk.Button(tree_buttons, text="折叠全部", command=collapse_all).pack(side=tk.LEFT, padx=5)
    tk.Button(tree_buttons, text="添加项目", command=add_item).pack(side=tk.LEFT, padx=5)
    tk.Button(tree_buttons, text="删除项目", command=delete_item).pack(side=tk.LEFT, padx=5)
    
    # 3. 组合框演示
    print("\n3. 组合框控件演示")
    
    combo_frame = tk.Frame(notebook)
    notebook.add(combo_frame, text="组合框")
    
    tk.Label(combo_frame, text="组合框控件演示", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    combo_container = tk.Frame(combo_frame)
    combo_container.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
    
    # 只读组合框
    readonly_frame = tk.LabelFrame(combo_container, text="只读组合框", padx=10, pady=10)
    readonly_frame.pack(fill=tk.X, pady=5)
    
    tk.Label(readonly_frame, text="选择编程语言:").pack(anchor=tk.W)
    
    readonly_var = tk.StringVar()
    readonly_combo = ttk.Combobox(readonly_frame, textvariable=readonly_var, 
                                 values=languages, state="readonly", width=30)
    readonly_combo.pack(pady=5, anchor=tk.W)
    readonly_combo.set("Python")  # 设置默认值
    
    def on_readonly_select(event):
        selected = readonly_var.get()
        print(f"    选择了编程语言: {selected}")
    
    readonly_combo.bind("<<ComboboxSelected>>", on_readonly_select)
    
    # 可编辑组合框
    editable_frame = tk.LabelFrame(combo_container, text="可编辑组合框", padx=10, pady=10)
    editable_frame.pack(fill=tk.X, pady=5)
    
    tk.Label(editable_frame, text="输入或选择城市:").pack(anchor=tk.W)
    
    editable_var = tk.StringVar()
    editable_combo = ttk.Combobox(editable_frame, textvariable=editable_var, 
                                 values=cities, width=30)
    editable_combo.pack(pady=5, anchor=tk.W)
    
    def on_editable_change(event):
        current = editable_var.get()
        print(f"    当前输入: {current}")
    
    editable_combo.bind("<KeyRelease>", on_editable_change)
    editable_combo.bind("<<ComboboxSelected>>", on_editable_change)
    
    # 动态组合框
    dynamic_frame = tk.LabelFrame(combo_container, text="动态组合框", padx=10, pady=10)
    dynamic_frame.pack(fill=tk.X, pady=5)
    
    tk.Label(dynamic_frame, text="类别:").pack(anchor=tk.W)
    
    category_var = tk.StringVar()
    category_combo = ttk.Combobox(dynamic_frame, textvariable=category_var, 
                                 values=["水果", "蔬菜", "肉类"], state="readonly", width=30)
    category_combo.pack(pady=5, anchor=tk.W)
    
    tk.Label(dynamic_frame, text="具体项目:").pack(anchor=tk.W)
    
    item_var = tk.StringVar()
    item_combo = ttk.Combobox(dynamic_frame, textvariable=item_var, 
                             state="readonly", width=30)
    item_combo.pack(pady=5, anchor=tk.W)
    
    # 动态更新选项
    category_items = {
        "水果": ["苹果", "香蕉", "橙子", "葡萄", "草莓"],
        "蔬菜": ["白菜", "萝卜", "土豆", "西红柿", "黄瓜"],
        "肉类": ["猪肉", "牛肉", "鸡肉", "鱼肉", "羊肉"]
    }
    
    def update_items(event):
        category = category_var.get()
        if category in category_items:
            item_combo['values'] = category_items[category]
            item_combo.set("")  # 清空当前选择
    
    category_combo.bind("<<ComboboxSelected>>", update_items)
    
    # 显示选择结果
    result_frame = tk.Frame(combo_container)
    result_frame.pack(fill=tk.X, pady=10)
    
    def show_selections():
        results = []
        if readonly_var.get():
            results.append(f"编程语言: {readonly_var.get()}")
        if editable_var.get():
            results.append(f"城市: {editable_var.get()}")
        if category_var.get() and item_var.get():
            results.append(f"食物: {category_var.get()} - {item_var.get()}")
        
        if results:
            messagebox.showinfo("选择结果", "\n".join(results))
        else:
            messagebox.showinfo("选择结果", "没有任何选择")
    
    tk.Button(result_frame, text="显示所有选择", command=show_selections).pack()
    
    print("\n列表和树形控件演示窗口已创建,请查看GUI界面")
    print("关闭窗口以继续下一个演示")
    
    # 启动事件循环
    root.mainloop()

# 运行列表和树形控件演示
list_tree_demo()

# 4.3 画布控件

import tkinter as tk
from tkinter import ttk, colorchooser
import math
import random

def canvas_demo():
    """画布控件演示"""
    print("=== 画布控件演示 ===")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("画布控件演示")
    root.geometry("1000x700")
    
    # 创建笔记本控件
    notebook = ttk.Notebook(root)
    notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
    
    # 1. 基础绘图
    print("\n1. 基础绘图演示")
    
    basic_frame = tk.Frame(notebook)
    notebook.add(basic_frame, text="基础绘图")
    
    tk.Label(basic_frame, text="基础绘图演示", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    # 创建画布
    basic_canvas = tk.Canvas(basic_frame, width=600, height=400, bg="white", relief=tk.SUNKEN, bd=2)
    basic_canvas.pack(pady=10)
    
    # 绘制基本图形
    def draw_basic_shapes():
        basic_canvas.delete("all")  # 清空画布
        
        # 绘制线条
        basic_canvas.create_line(50, 50, 200, 50, fill="red", width=3)
        basic_canvas.create_line(50, 70, 200, 120, fill="blue", width=2)
        
        # 绘制矩形
        basic_canvas.create_rectangle(250, 50, 350, 120, fill="lightblue", outline="blue", width=2)
        basic_canvas.create_rectangle(370, 50, 470, 120, fill="", outline="green", width=3)
        
        # 绘制椭圆
        basic_canvas.create_oval(50, 150, 150, 220, fill="yellow", outline="orange", width=2)
        basic_canvas.create_oval(170, 150, 220, 200, fill="pink", outline="red")
        
        # 绘制多边形
        points = [250, 150, 300, 180, 350, 150, 370, 200, 280, 220, 230, 200]
        basic_canvas.create_polygon(points, fill="lightgreen", outline="darkgreen", width=2)
        
        # 绘制弧形
        basic_canvas.create_arc(400, 150, 500, 220, start=0, extent=180, fill="lightcoral", outline="red", width=2)
        basic_canvas.create_arc(520, 150, 580, 220, start=45, extent=90, fill="", outline="purple", width=3, style=tk.ARC)
        
        # 绘制文本
        basic_canvas.create_text(300, 250, text="Canvas绘图演示", font=("Arial", 16, "bold"), fill="blue")
        basic_canvas.create_text(300, 280, text="支持多种图形和文本", font=("宋体", 12), fill="darkgreen")
        
        # 绘制图像(如果有的话)
        # photo = tk.PhotoImage(file="image.png")
        # basic_canvas.create_image(300, 350, image=photo)
    
    # 绘图控制按钮
    basic_buttons = tk.Frame(basic_frame)
    basic_buttons.pack(pady=5)
    
    tk.Button(basic_buttons, text="绘制图形", command=draw_basic_shapes).pack(side=tk.LEFT, padx=5)
    tk.Button(basic_buttons, text="清空画布", command=lambda: basic_canvas.delete("all")).pack(side=tk.LEFT, padx=5)
    
    # 2. 交互式绘图
    print("\n2. 交互式绘图演示")
    
    interactive_frame = tk.Frame(notebook)
    notebook.add(interactive_frame, text="交互绘图")
    
    tk.Label(interactive_frame, text="交互式绘图演示", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    # 工具栏
    toolbar = tk.Frame(interactive_frame)
    toolbar.pack(fill=tk.X, padx=10, pady=5)
    
    # 绘图模式
    draw_mode = tk.StringVar(value="line")
    
    tk.Label(toolbar, text="绘图工具:").pack(side=tk.LEFT, padx=5)
    
    modes = [("线条", "line"), ("矩形", "rectangle"), ("椭圆", "oval"), ("自由绘制", "free")]
    for text, mode in modes:
        tk.Radiobutton(toolbar, text=text, variable=draw_mode, value=mode).pack(side=tk.LEFT, padx=2)
    
    # 颜色选择
    current_color = tk.StringVar(value="black")
    
    def choose_color():
        color = colorchooser.askcolor(title="选择颜色")
        if color[1]:
            current_color.set(color[1])
            color_label.config(bg=color[1])
    
    tk.Label(toolbar, text="颜色:").pack(side=tk.LEFT, padx=(20, 5))
    color_label = tk.Label(toolbar, bg="black", width=3, relief=tk.RAISED, cursor="hand2")
    color_label.pack(side=tk.LEFT, padx=2)
    color_label.bind("<Button-1>", lambda e: choose_color())
    
    # 线条粗细
    tk.Label(toolbar, text="粗细:").pack(side=tk.LEFT, padx=(20, 5))
    line_width = tk.Scale(toolbar, from_=1, to=10, orient=tk.HORIZONTAL, length=100)
    line_width.set(2)
    line_width.pack(side=tk.LEFT, padx=2)
    
    # 创建交互画布
    interactive_canvas = tk.Canvas(interactive_frame, width=700, height=450, bg="white", relief=tk.SUNKEN, bd=2)
    interactive_canvas.pack(pady=10)
    
    # 绘图状态变量
    drawing = False
    start_x = start_y = 0
    current_item = None
    
    def start_draw(event):
        global drawing, start_x, start_y, current_item
        drawing = True
        start_x, start_y = event.x, event.y
        
        mode = draw_mode.get()
        color = current_color.get()
        width = line_width.get()
        
        if mode == "free":
            # 自由绘制模式,立即开始绘制
            current_item = interactive_canvas.create_line(start_x, start_y, start_x, start_y, 
                                                        fill=color, width=width, capstyle=tk.ROUND)
    
    def draw(event):
        global current_item
        if not drawing:
            return
        
        mode = draw_mode.get()
        color = current_color.get()
        width = line_width.get()
        
        if mode == "line":
            # 删除之前的预览线条
            if current_item:
                interactive_canvas.delete(current_item)
            # 绘制新的预览线条
            current_item = interactive_canvas.create_line(start_x, start_y, event.x, event.y, 
                                                        fill=color, width=width)
        
        elif mode == "rectangle":
            if current_item:
                interactive_canvas.delete(current_item)
            current_item = interactive_canvas.create_rectangle(start_x, start_y, event.x, event.y, 
                                                             outline=color, width=width)
        
        elif mode == "oval":
            if current_item:
                interactive_canvas.delete(current_item)
            current_item = interactive_canvas.create_oval(start_x, start_y, event.x, event.y, 
                                                        outline=color, width=width)
        
        elif mode == "free":
            # 自由绘制模式,扩展当前线条
            coords = interactive_canvas.coords(current_item)
            coords.extend([event.x, event.y])
            interactive_canvas.coords(current_item, *coords)
    
    def end_draw(event):
        global drawing, current_item
        drawing = False
        current_item = None
    
    # 绑定鼠标事件
    interactive_canvas.bind("<Button-1>", start_draw)
    interactive_canvas.bind("<B1-Motion>", draw)
    interactive_canvas.bind("<ButtonRelease-1>", end_draw)
    
    # 交互控制按钮
    interactive_buttons = tk.Frame(interactive_frame)
    interactive_buttons.pack(pady=5)
    
    def clear_canvas():
        interactive_canvas.delete("all")
    
    def save_canvas():
        # 这里可以实现保存功能
        print("    保存画布内容(需要额外的库支持)")
    
    tk.Button(interactive_buttons, text="清空画布", command=clear_canvas).pack(side=tk.LEFT, padx=5)
    tk.Button(interactive_buttons, text="保存画布", command=save_canvas).pack(side=tk.LEFT, padx=5)
    
    # 3. 动画演示
    print("\n3. 动画演示")
    
    animation_frame = tk.Frame(notebook)
    notebook.add(animation_frame, text="动画演示")
    
    tk.Label(animation_frame, text="动画演示", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    # 创建动画画布
    anim_canvas = tk.Canvas(animation_frame, width=600, height=400, bg="black", relief=tk.SUNKEN, bd=2)
    anim_canvas.pack(pady=10)
    
    # 动画对象
    class AnimatedBall:
        def __init__(self, canvas, x, y, dx, dy, radius, color):
            self.canvas = canvas
            self.x = x
            self.y = y
            self.dx = dx
            self.dy = dy
            self.radius = radius
            self.color = color
            self.item = canvas.create_oval(x-radius, y-radius, x+radius, y+radius, 
                                         fill=color, outline="white")
        
        def move(self):
            # 更新位置
            self.x += self.dx
            self.y += self.dy
            
            # 边界检测
            canvas_width = int(self.canvas.cget("width"))
            canvas_height = int(self.canvas.cget("height"))
            
            if self.x - self.radius <= 0 or self.x + self.radius >= canvas_width:
                self.dx = -self.dx
            if self.y - self.radius <= 0 or self.y + self.radius >= canvas_height:
                self.dy = -self.dy
            
            # 更新画布上的位置
            self.canvas.coords(self.item, 
                             self.x - self.radius, self.y - self.radius,
                             self.x + self.radius, self.y + self.radius)
    
    # 创建多个动画球
    balls = []
    colors = ["red", "blue", "green", "yellow", "orange", "purple", "cyan", "magenta"]
    
    def create_balls():
        anim_canvas.delete("all")
        balls.clear()
        
        for i in range(8):
            x = random.randint(50, 550)
            y = random.randint(50, 350)
            dx = random.randint(-5, 5)
            dy = random.randint(-5, 5)
            if dx == 0: dx = 1
            if dy == 0: dy = 1
            radius = random.randint(10, 25)
            color = colors[i]
            
            ball = AnimatedBall(anim_canvas, x, y, dx, dy, radius, color)
            balls.append(ball)
    
    # 动画控制
    animation_running = False
    
    def animate():
        if animation_running:
            for ball in balls:
                ball.move()
            root.after(50, animate)  # 每50毫秒更新一次
    
    def start_animation():
        global animation_running
        if not animation_running:
            animation_running = True
            animate()
    
    def stop_animation():
        global animation_running
        animation_running = False
    
    # 动画控制按钮
    anim_buttons = tk.Frame(animation_frame)
    anim_buttons.pack(pady=5)
    
    tk.Button(anim_buttons, text="创建球", command=create_balls).pack(side=tk.LEFT, padx=5)
    tk.Button(anim_buttons, text="开始动画", command=start_animation).pack(side=tk.LEFT, padx=5)
    tk.Button(anim_buttons, text="停止动画", command=stop_animation).pack(side=tk.LEFT, padx=5)
    
    # 4. 图表绘制
    print("\n4. 图表绘制演示")
    
    chart_frame = tk.Frame(notebook)
    notebook.add(chart_frame, text="图表绘制")
    
    tk.Label(chart_frame, text="图表绘制演示", 
            font=("Arial", 14, "bold")).pack(pady=10)
    
    # 创建图表画布
    chart_canvas = tk.Canvas(chart_frame, width=700, height=450, bg="white", relief=tk.SUNKEN, bd=2)
    chart_canvas.pack(pady=10)
    
    def draw_bar_chart():
        chart_canvas.delete("all")
        
        # 示例数据
        data = {"Python": 85, "Java": 70, "JavaScript": 65, "C++": 60, "Go": 45}
        
        # 图表参数
        margin = 50
        chart_width = 600
        chart_height = 350
        bar_width = (chart_width - 2 * margin) // len(data)
        max_value = max(data.values())
        
        # 绘制坐标轴
        chart_canvas.create_line(margin, margin, margin, chart_height + margin, width=2)  # Y轴
        chart_canvas.create_line(margin, chart_height + margin, 
                               chart_width + margin, chart_height + margin, width=2)  # X轴
        
        # 绘制标题
        chart_canvas.create_text(chart_width // 2 + margin, 20, 
                               text="编程语言流行度", font=("Arial", 16, "bold"))
        
        # 绘制柱状图
        colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FFEAA7"]
        x = margin + 10
        
        for i, (lang, value) in enumerate(data.items()):
            # 计算柱子高度
            bar_height = (value / max_value) * (chart_height - 20)
            
            # 绘制柱子
            chart_canvas.create_rectangle(x, chart_height + margin - bar_height,
                                        x + bar_width - 20, chart_height + margin,
                                        fill=colors[i % len(colors)], outline="black")
            
            # 绘制标签
            chart_canvas.create_text(x + (bar_width - 20) // 2, chart_height + margin + 15,
                                   text=lang, font=("Arial", 10))
            
            # 绘制数值
            chart_canvas.create_text(x + (bar_width - 20) // 2, 
                                   chart_height + margin - bar_height - 10,
                                   text=str(value), font=("Arial", 10, "bold"))
            
            x += bar_width
    
    def draw_line_chart():
        chart_canvas.delete("all")
        
        # 示例数据
        months = ["1月", "2月", "3月", "4月", "5月", "6月"]
        sales = [120, 150, 180, 200, 170, 220]
        
        # 图表参数
        margin = 50
        chart_width = 600
        chart_height = 350
        
        # 绘制坐标轴
        chart_canvas.create_line(margin, margin, margin, chart_height + margin, width=2)
        chart_canvas.create_line(margin, chart_height + margin, 
                               chart_width + margin, chart_height + margin, width=2)
        
        # 绘制标题
        chart_canvas.create_text(chart_width // 2 + margin, 20, 
                               text="月度销售趋势", font=("Arial", 16, "bold"))
        
        # 计算点的位置
        x_step = chart_width // (len(months) - 1)
        max_sales = max(sales)
        min_sales = min(sales)
        
        points = []
        for i, sale in enumerate(sales):
            x = margin + i * x_step
            y = chart_height + margin - ((sale - min_sales) / (max_sales - min_sales)) * (chart_height - 20)
            points.extend([x, y])
            
            # 绘制数据点
            chart_canvas.create_oval(x-4, y-4, x+4, y+4, fill="red", outline="darkred")
            
            # 绘制数值标签
            chart_canvas.create_text(x, y-15, text=str(sale), font=("Arial", 10, "bold"))
            
            # 绘制月份标签
            chart_canvas.create_text(x, chart_height + margin + 15, 
                                   text=months[i], font=("Arial", 10))
        
        # 绘制折线
        chart_canvas.create_line(points, fill="blue", width=3, smooth=True)
    
    def draw_pie_chart():
        chart_canvas.delete("all")
        
        # 示例数据
        data = {"桌面": 40, "移动": 35, "平板": 15, "其他": 10}
        colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4"]
        
        # 饼图参数
        center_x, center_y = 350, 225
        radius = 120
        
        # 绘制标题
        chart_canvas.create_text(center_x, 50, text="设备使用分布", font=("Arial", 16, "bold"))
        
        # 计算角度
        total = sum(data.values())
        start_angle = 0
        
        for i, (category, value) in enumerate(data.items()):
            # 计算扇形角度
            extent = (value / total) * 360
            
            # 绘制扇形
            chart_canvas.create_arc(center_x - radius, center_y - radius,
                                  center_x + radius, center_y + radius,
                                  start=start_angle, extent=extent,
                                  fill=colors[i % len(colors)], outline="white", width=2)
            
            # 计算标签位置
            label_angle = math.radians(start_angle + extent / 2)
            label_x = center_x + (radius + 30) * math.cos(label_angle)
            label_y = center_y + (radius + 30) * math.sin(label_angle)
            
            # 绘制标签
            chart_canvas.create_text(label_x, label_y, 
                                   text=f"{category}\n{value}%", 
                                   font=("Arial", 10), justify=tk.CENTER)
            
            start_angle += extent
    
    # 图表控制按钮
    chart_buttons = tk.Frame(chart_frame)
    chart_buttons.pack(pady=5)
    
    tk.Button(chart_buttons, text="柱状图", command=draw_bar_chart).pack(side=tk.LEFT, padx=5)
    tk.Button(chart_buttons, text="折线图", command=draw_line_chart).pack(side=tk.LEFT, padx=5)
    tk.Button(chart_buttons, text="饼图", command=draw_pie_chart).pack(side=tk.LEFT, padx=5)
    tk.Button(chart_buttons, text="清空", command=lambda: chart_canvas.delete("all")).pack(side=tk.LEFT, padx=5)
    
    # 初始化
    draw_basic_shapes()
    create_balls()
    draw_bar_chart()
    
    print("\n画布控件演示窗口已创建,请查看GUI界面")
    print("尝试不同的绘图和动画功能")
    print("关闭窗口以继续下一个演示")
    
    # 窗口关闭事件
    def on_closing():
        stop_animation()  # 停止动画
        root.destroy()
    
    root.protocol("WM_DELETE_WINDOW", on_closing)
    
    # 启动事件循环
    root.mainloop()

# 运行画布控件演示
canvas_demo()

# 5. 实际项目示例

# 5.1 简单计算器

import tkinter as tk
from tkinter import ttk, messagebox
import math

def calculator_app():
    """简单计算器应用"""
    print("=== 计算器应用演示 ===")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Python计算器")
    root.geometry("350x500")
    root.resizable(False, False)
    
    # 设置样式
    style = ttk.Style()
    style.theme_use('clam')
    
    # 计算器状态
    current_input = tk.StringVar(value="0")
    operator = ""
    first_number = 0
    should_reset = False
    
    # 显示屏
    display_frame = tk.Frame(root, bg="black", padx=10, pady=10)
    display_frame.pack(fill=tk.X)
    
    display = tk.Label(display_frame, textvariable=current_input, 
                      font=("Arial", 24, "bold"), bg="black", fg="white", 
                      anchor="e", padx=10, pady=10)
    display.pack(fill=tk.X)
    
    # 按钮框架
    button_frame = tk.Frame(root, padx=10, pady=10)
    button_frame.pack(fill=tk.BOTH, expand=True)
    
    # 按钮样式配置
    button_config = {
        'font': ('Arial', 16, 'bold'),
        'width': 4,
        'height': 2
    }
    
    def clear_all():
        """清除所有"""
        global operator, first_number, should_reset
        current_input.set("0")
        operator = ""
        first_number = 0
        should_reset = False
    
    def clear_entry():
        """清除当前输入"""
        current_input.set("0")
    
    def backspace():
        """退格"""
        current = current_input.get()
        if len(current) > 1:
            current_input.set(current[:-1])
        else:
            current_input.set("0")
    
    def input_number(num):
        """输入数字"""
        global should_reset
        current = current_input.get()
        
        if should_reset or current == "0":
            current_input.set(str(num))
            should_reset = False
        else:
            current_input.set(current + str(num))
    
    def input_decimal():
        """输入小数点"""
        global should_reset
        current = current_input.get()
        
        if should_reset:
            current_input.set("0.")
            should_reset = False
        elif "." not in current:
            current_input.set(current + ".")
    
    def input_operator(op):
        """输入运算符"""
        global operator, first_number, should_reset
        
        try:
            first_number = float(current_input.get())
            operator = op
            should_reset = True
        except ValueError:
            messagebox.showerror("错误", "无效的数字")
    
    def calculate():
        """计算结果"""
        global operator, first_number, should_reset
        
        try:
            second_number = float(current_input.get())
            
            if operator == "+":
                result = first_number + second_number
            elif operator == "-":
                result = first_number - second_number
            elif operator == "×":
                result = first_number * second_number
            elif operator == "÷":
                if second_number == 0:
                    messagebox.showerror("错误", "除数不能为零")
                    return
                result = first_number / second_number
            elif operator == "^":
                result = first_number ** second_number
            else:
                return
            
            # 格式化结果
            if result == int(result):
                current_input.set(str(int(result)))
            else:
                current_input.set(f"{result:.10g}")
            
            operator = ""
            should_reset = True
            
        except ValueError:
            messagebox.showerror("错误", "无效的数字")
        except Exception as e:
            messagebox.showerror("错误", f"计算错误: {str(e)}")
    
    def calculate_sqrt():
        """计算平方根"""
        try:
            number = float(current_input.get())
            if number < 0:
                messagebox.showerror("错误", "负数不能开平方根")
                return
            result = math.sqrt(number)
            current_input.set(f"{result:.10g}")
        except ValueError:
            messagebox.showerror("错误", "无效的数字")
    
    def calculate_percent():
        """计算百分比"""
        try:
            number = float(current_input.get())
            result = number / 100
            current_input.set(f"{result:.10g}")
        except ValueError:
            messagebox.showerror("错误", "无效的数字")
    
    def toggle_sign():
        """切换正负号"""
        try:
            number = float(current_input.get())
            result = -number
            if result == int(result):
                current_input.set(str(int(result)))
            else:
                current_input.set(f"{result:.10g}")
        except ValueError:
            messagebox.showerror("错误", "无效的数字")
    
    # 创建按钮
    buttons = [
        # 第一行
        [("C", clear_all, "#FF6B6B"), ("CE", clear_entry, "#FF8E53"), ("⌫", backspace, "#FF8E53"), ("÷", lambda: input_operator("÷"), "#4ECDC4")],
        # 第二行
        [("7", lambda: input_number(7), "#E8E8E8"), ("8", lambda: input_number(8), "#E8E8E8"), ("9", lambda: input_number(9), "#E8E8E8"), ("×", lambda: input_operator("×"), "#4ECDC4")],
        # 第三行
        [("4", lambda: input_number(4), "#E8E8E8"), ("5", lambda: input_number(5), "#E8E8E8"), ("6", lambda: input_number(6), "#E8E8E8"), ("-", lambda: input_operator("-"), "#4ECDC4")],
        # 第四行
        [("1", lambda: input_number(1), "#E8E8E8"), ("2", lambda: input_number(2), "#E8E8E8"), ("3", lambda: input_number(3), "#E8E8E8"), ("+", lambda: input_operator("+"), "#4ECDC4")],
        # 第五行
        [("±", toggle_sign, "#D3D3D3"), ("0", lambda: input_number(0), "#E8E8E8"), (".", input_decimal, "#E8E8E8"), ("=", calculate, "#45B7D1")],
        # 第六行
        [("√", calculate_sqrt, "#96CEB4"), ("%", calculate_percent, "#96CEB4"), ("^", lambda: input_operator("^"), "#4ECDC4"), ("", None, "")]
    ]
    
    for row_idx, row in enumerate(buttons):
        for col_idx, (text, command, color) in enumerate(row):
            if text:  # 跳过空按钮
                btn = tk.Button(button_frame, text=text, command=command, 
                               bg=color, fg="black" if color != "#45B7D1" else "white",
                               activebackground=color, **button_config)
                btn.grid(row=row_idx, column=col_idx, padx=2, pady=2, sticky="nsew")
    
    # 配置网格权重
    for i in range(4):
        button_frame.grid_columnconfigure(i, weight=1)
    for i in range(6):
        button_frame.grid_rowconfigure(i, weight=1)
    
    # 键盘绑定
    def on_key_press(event):
        key = event.char
        if key.isdigit():
            input_number(int(key))
        elif key == ".":
            input_decimal()
        elif key in "+-*/":
            op_map = {"+": "+", "-": "-", "*": "×", "/": "÷"}
            input_operator(op_map[key])
        elif key in "\r\n=":  # Enter键或等号
            calculate()
        elif event.keysym == "BackSpace":
            backspace()
        elif event.keysym == "Escape":
            clear_all()
    
    root.bind("<Key>", on_key_press)
    root.focus_set()  # 设置焦点以接收键盘事件
    
    print("\n计算器应用已启动")
    print("支持鼠标点击和键盘输入")
    print("键盘快捷键: 数字键、运算符、Enter(=)、Backspace、Esc(清除)")
    
    # 启动事件循环
    root.mainloop()

# 运行计算器应用
calculator_app()

# 5.2 文本编辑器

import tkinter as tk
from tkinter import ttk, filedialog, messagebox, font
import os

def text_editor_app():
    """简单文本编辑器应用"""
    print("=== 文本编辑器应用演示 ===")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Python文本编辑器")
    root.geometry("800x600")
    
    # 应用状态
    current_file = None
    is_modified = False
    
    def update_title():
        """更新窗口标题"""
        title = "Python文本编辑器"
        if current_file:
            title += f" - {os.path.basename(current_file)}"
        if is_modified:
            title += " *"
        root.title(title)
    
    def mark_modified():
        """标记文件已修改"""
        global is_modified
        if not is_modified:
            is_modified = True
            update_title()
    
    def mark_saved():
        """标记文件已保存"""
        global is_modified
        is_modified = False
        update_title()
    
    # 创建菜单栏
    menubar = tk.Menu(root)
    root.config(menu=menubar)
    
    # 文件菜单
    file_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="文件", menu=file_menu)
    
    def new_file():
        """新建文件"""
        global current_file
        if is_modified:
            response = messagebox.askyesnocancel("保存", "文件已修改,是否保存?")
            if response is True:
                save_file()
            elif response is None:
                return
        
        text_area.delete(1.0, tk.END)
        current_file = None
        mark_saved()
    
    def open_file():
        """打开文件"""
        global current_file
        if is_modified:
            response = messagebox.askyesnocancel("保存", "文件已修改,是否保存?")
            if response is True:
                save_file()
            elif response is None:
                return
        
        file_path = filedialog.askopenfilename(
            title="打开文件",
            filetypes=[("文本文件", "*.txt"), ("Python文件", "*.py"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                with open(file_path, 'r', encoding='utf-8') as file:
                    content = file.read()
                    text_area.delete(1.0, tk.END)
                    text_area.insert(1.0, content)
                    current_file = file_path
                    mark_saved()
            except Exception as e:
                messagebox.showerror("错误", f"无法打开文件: {str(e)}")
    
    def save_file():
        """保存文件"""
        global current_file
        if current_file:
            try:
                content = text_area.get(1.0, tk.END + "-1c")
                with open(current_file, 'w', encoding='utf-8') as file:
                    file.write(content)
                mark_saved()
                messagebox.showinfo("保存", "文件保存成功")
            except Exception as e:
                messagebox.showerror("错误", f"无法保存文件: {str(e)}")
        else:
            save_as_file()
    
    def save_as_file():
        """另存为文件"""
        global current_file
        file_path = filedialog.asksaveasfilename(
            title="另存为",
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("Python文件", "*.py"), ("所有文件", "*.*")]
        )
        
        if file_path:
            try:
                content = text_area.get(1.0, tk.END + "-1c")
                with open(file_path, 'w', encoding='utf-8') as file:
                    file.write(content)
                current_file = file_path
                mark_saved()
                messagebox.showinfo("保存", "文件保存成功")
            except Exception as e:
                messagebox.showerror("错误", f"无法保存文件: {str(e)}")
    
    def exit_app():
        """退出应用"""
        if is_modified:
            response = messagebox.askyesnocancel("保存", "文件已修改,是否保存?")
            if response is True:
                save_file()
            elif response is None:
                return
        root.quit()
    
    file_menu.add_command(label="新建", command=new_file, accelerator="Ctrl+N")
    file_menu.add_command(label="打开", command=open_file, accelerator="Ctrl+O")
    file_menu.add_separator()
    file_menu.add_command(label="保存", command=save_file, accelerator="Ctrl+S")
    file_menu.add_command(label="另存为", command=save_as_file, accelerator="Ctrl+Shift+S")
    file_menu.add_separator()
    file_menu.add_command(label="退出", command=exit_app, accelerator="Ctrl+Q")
    
    # 编辑菜单
    edit_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="编辑", menu=edit_menu)
    
    def undo():
        try:
            text_area.edit_undo()
        except tk.TclError:
            pass
    
    def redo():
        try:
            text_area.edit_redo()
        except tk.TclError:
            pass
    
    def cut():
        try:
            text_area.event_generate("<<Cut>>")
        except tk.TclError:
            pass
    
    def copy():
        try:
            text_area.event_generate("<<Copy>>")
        except tk.TclError:
            pass
    
    def paste():
        try:
            text_area.event_generate("<<Paste>>")
        except tk.TclError:
            pass
    
    def select_all():
        text_area.tag_add(tk.SEL, "1.0", tk.END)
        text_area.mark_set(tk.INSERT, "1.0")
        text_area.see(tk.INSERT)
    
    def find_text():
        """查找文本"""
        find_window = tk.Toplevel(root)
        find_window.title("查找")
        find_window.geometry("300x100")
        find_window.resizable(False, False)
        
        tk.Label(find_window, text="查找:").pack(pady=5)
        
        search_var = tk.StringVar()
        search_entry = tk.Entry(find_window, textvariable=search_var, width=30)
        search_entry.pack(pady=5)
        search_entry.focus()
        
        def do_find():
            search_text = search_var.get()
            if search_text:
                # 清除之前的高亮
                text_area.tag_remove("found", "1.0", tk.END)
                
                # 查找并高亮
                start = "1.0"
                while True:
                    pos = text_area.search(search_text, start, tk.END)
                    if not pos:
                        break
                    end = f"{pos}+{len(search_text)}c"
                    text_area.tag_add("found", pos, end)
                    start = end
                
                # 设置高亮样式
                text_area.tag_config("found", background="yellow")
                
                # 跳转到第一个匹配项
                first_match = text_area.search(search_text, "1.0", tk.END)
                if first_match:
                    text_area.see(first_match)
                    text_area.mark_set(tk.INSERT, first_match)
        
        tk.Button(find_window, text="查找", command=do_find).pack(pady=5)
    
    edit_menu.add_command(label="撤销", command=undo, accelerator="Ctrl+Z")
    edit_menu.add_command(label="重做", command=redo, accelerator="Ctrl+Y")
    edit_menu.add_separator()
    edit_menu.add_command(label="剪切", command=cut, accelerator="Ctrl+X")
    edit_menu.add_command(label="复制", command=copy, accelerator="Ctrl+C")
    edit_menu.add_command(label="粘贴", command=paste, accelerator="Ctrl+V")
    edit_menu.add_separator()
    edit_menu.add_command(label="全选", command=select_all, accelerator="Ctrl+A")
    edit_menu.add_command(label="查找", command=find_text, accelerator="Ctrl+F")
    
    # 格式菜单
    format_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="格式", menu=format_menu)
    
    def change_font():
        """更改字体"""
        font_window = tk.Toplevel(root)
        font_window.title("字体设置")
        font_window.geometry("400x300")
        
        current_font = font.Font(font=text_area['font'])
        
        # 字体族
        tk.Label(font_window, text="字体:").grid(row=0, column=0, sticky="w", padx=5, pady=5)
        font_family = tk.StringVar(value=current_font.actual()['family'])
        font_listbox = tk.Listbox(font_window, height=6)
        font_listbox.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="ew")
        
        families = sorted(font.families())
        for family in families:
            font_listbox.insert(tk.END, family)
        
        # 字体大小
        tk.Label(font_window, text="大小:").grid(row=2, column=0, sticky="w", padx=5, pady=5)
        size_var = tk.StringVar(value=str(current_font.actual()['size']))
        size_entry = tk.Entry(font_window, textvariable=size_var, width=10)
        size_entry.grid(row=2, column=1, padx=5, pady=5, sticky="w")
        
        # 字体样式
        bold_var = tk.BooleanVar(value=current_font.actual()['weight'] == 'bold')
        italic_var = tk.BooleanVar(value=current_font.actual()['slant'] == 'italic')
        
        tk.Checkbutton(font_window, text="粗体", variable=bold_var).grid(row=3, column=0, sticky="w", padx=5, pady=5)
        tk.Checkbutton(font_window, text="斜体", variable=italic_var).grid(row=3, column=1, sticky="w", padx=5, pady=5)
        
        def apply_font():
            try:
                selection = font_listbox.curselection()
                if selection:
                    family = font_listbox.get(selection[0])
                else:
                    family = current_font.actual()['family']
                
                size = int(size_var.get())
                weight = 'bold' if bold_var.get() else 'normal'
                slant = 'italic' if italic_var.get() else 'roman'
                
                new_font = font.Font(family=family, size=size, weight=weight, slant=slant)
                text_area.config(font=new_font)
                font_window.destroy()
            except ValueError:
                messagebox.showerror("错误", "请输入有效的字体大小")
        
        tk.Button(font_window, text="应用", command=apply_font).grid(row=4, column=0, columnspan=2, pady=10)
    
    format_menu.add_command(label="字体", command=change_font)
    
    # 帮助菜单
    help_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="帮助", menu=help_menu)
    
    def show_about():
        messagebox.showinfo("关于", "Python文本编辑器\n\n一个简单的文本编辑器示例\n使用Tkinter构建")
    
    help_menu.add_command(label="关于", command=show_about)
    
    # 创建工具栏
    toolbar = tk.Frame(root, relief=tk.RAISED, bd=1)
    toolbar.pack(side=tk.TOP, fill=tk.X)
    
    # 工具栏按钮
    tk.Button(toolbar, text="新建", command=new_file, width=6).pack(side=tk.LEFT, padx=2, pady=2)
    tk.Button(toolbar, text="打开", command=open_file, width=6).pack(side=tk.LEFT, padx=2, pady=2)
    tk.Button(toolbar, text="保存", command=save_file, width=6).pack(side=tk.LEFT, padx=2, pady=2)
    
    ttk.Separator(toolbar, orient=tk.VERTICAL).pack(side=tk.LEFT, fill=tk.Y, padx=5)
    
    tk.Button(toolbar, text="剪切", command=cut, width=6).pack(side=tk.LEFT, padx=2, pady=2)
    tk.Button(toolbar, text="复制", command=copy, width=6).pack(side=tk.LEFT, padx=2, pady=2)
    tk.Button(toolbar, text="粘贴", command=paste, width=6).pack(side=tk.LEFT, padx=2, pady=2)
    
    # 创建文本区域
    text_frame = tk.Frame(root)
    text_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
    
    # 文本控件
    text_area = tk.Text(text_frame, wrap=tk.WORD, undo=True, font=("Consolas", 12))
    
    # 滚动条
    v_scrollbar = tk.Scrollbar(text_frame, orient=tk.VERTICAL, command=text_area.yview)
    h_scrollbar = tk.Scrollbar(text_frame, orient=tk.HORIZONTAL, command=text_area.xview)
    
    text_area.config(yscrollcommand=v_scrollbar.set, xscrollcommand=h_scrollbar.set)
    
    # 布局
    text_area.grid(row=0, column=0, sticky="nsew")
    v_scrollbar.grid(row=0, column=1, sticky="ns")
    h_scrollbar.grid(row=1, column=0, sticky="ew")
    
    text_frame.grid_rowconfigure(0, weight=1)
    text_frame.grid_columnconfigure(0, weight=1)
    
    # 状态栏
    status_bar = tk.Frame(root, relief=tk.SUNKEN, bd=1)
    status_bar.pack(side=tk.BOTTOM, fill=tk.X)
    
    # 状态标签
    line_col_label = tk.Label(status_bar, text="行: 1, 列: 1")
    line_col_label.pack(side=tk.RIGHT, padx=5)
    
    char_count_label = tk.Label(status_bar, text="字符数: 0")
    char_count_label.pack(side=tk.RIGHT, padx=5)
    
    def update_status(event=None):
        """更新状态栏"""
        # 获取光标位置
        cursor_pos = text_area.index(tk.INSERT)
        line, col = cursor_pos.split('.')
        line_col_label.config(text=f"行: {line}, 列: {int(col)+1}")
        
        # 获取字符数
        content = text_area.get(1.0, tk.END + "-1c")
        char_count_label.config(text=f"字符数: {len(content)}")
    
    # 绑定事件
    text_area.bind("<KeyRelease>", update_status)
    text_area.bind("<Button-1>", update_status)
    text_area.bind("<KeyPress>", lambda e: mark_modified())
    
    # 键盘快捷键
    root.bind("<Control-n>", lambda e: new_file())
    root.bind("<Control-o>", lambda e: open_file())
    root.bind("<Control-s>", lambda e: save_file())
    root.bind("<Control-Shift-S>", lambda e: save_as_file())
    root.bind("<Control-q>", lambda e: exit_app())
    root.bind("<Control-z>", lambda e: undo())
    root.bind("<Control-y>", lambda e: redo())
    root.bind("<Control-a>", lambda e: select_all())
    root.bind("<Control-f>", lambda e: find_text())
    
    # 窗口关闭事件
    root.protocol("WM_DELETE_WINDOW", exit_app)
    
    # 初始化状态
    update_status()
    update_title()
    
    print("\n文本编辑器应用已启动")
    print("支持基本的文本编辑功能")
    print("包括文件操作、编辑操作、格式设置等")
    
    # 启动事件循环
    root.mainloop()

# 运行文本编辑器应用
text_editor_app()

# 6. GUI编程最佳实践

# 6.1 设计原则

# GUI设计最佳实践示例

def gui_best_practices():
    """GUI编程最佳实践演示"""
    print("=== GUI编程最佳实践 ===")
    
    # 1. 用户体验原则
    print("\n1. 用户体验原则:")
    print("   - 界面简洁直观")
    print("   - 操作流程清晰")
    print("   - 提供及时反馈")
    print("   - 支持键盘快捷键")
    print("   - 错误处理友好")
    
    # 2. 布局设计
    print("\n2. 布局设计:")
    print("   - 使用合适的布局管理器")
    print("   - 保持界面元素对齐")
    print("   - 合理使用空白空间")
    print("   - 响应式设计")
    
    # 3. 代码组织
    print("\n3. 代码组织:")
    print("   - 分离界面和业务逻辑")
    print("   - 使用类封装GUI组件")
    print("   - 模块化设计")
    print("   - 异常处理")
    
    # 4. 性能优化
    print("\n4. 性能优化:")
    print("   - 避免阻塞UI线程")
    print("   - 使用虚拟化处理大量数据")
    print("   - 延迟加载")
    print("   - 内存管理")
    
    # 5. 可访问性
    print("\n5. 可访问性:")
    print("   - 支持键盘导航")
    print("   - 提供工具提示")
    print("   - 合适的颜色对比度")
    print("   - 字体大小可调")

# 运行最佳实践演示
gui_best_practices()

# 6.2 常见问题和解决方案

def common_issues_solutions():
    """常见问题和解决方案"""
    print("=== 常见问题和解决方案 ===")
    
    # 1. 界面冻结问题
    print("\n1. 界面冻结问题:")
    print("   问题: 长时间运行的任务导致界面无响应")
    print("   解决: 使用线程或after()方法")
    
    # 示例:使用after()方法避免界面冻结
    def long_task_example():
        root = tk.Tk()
        root.title("避免界面冻结示例")
        
        progress = ttk.Progressbar(root, length=300, mode='determinate')
        progress.pack(pady=20)
        
        status_label = tk.Label(root, text="准备开始...")
        status_label.pack(pady=10)
        
        def simulate_work(step=0):
            if step < 100:
                progress['value'] = step
                status_label.config(text=f"处理中... {step}%")
                # 使用after()方法避免阻塞UI
                root.after(50, lambda: simulate_work(step + 1))
            else:
                status_label.config(text="完成!")
        
        tk.Button(root, text="开始任务", command=simulate_work).pack(pady=10)
        
        return root
    
    # 2. 内存泄漏问题
    print("\n2. 内存泄漏问题:")
    print("   问题: 未正确销毁窗口和绑定")
    print("   解决: 正确使用destroy()和解绑事件")
    
    # 3. 跨平台兼容性
    print("\n3. 跨平台兼容性:")
    print("   问题: 不同操作系统显示效果不一致")
    print("   解决: 使用ttk主题控件,测试多平台")
    
    # 4. 高DPI显示问题
    print("\n4. 高DPI显示问题:")
    print("   问题: 在高DPI屏幕上显示模糊")
    print("   解决: 设置DPI感知")
    
    # 示例:DPI感知设置
    def set_dpi_awareness():
        try:
            from ctypes import windll
            windll.shcore.SetProcessDpiAwareness(1)
        except:
            pass  # 非Windows系统或不支持
    
    # 5. 数据绑定问题
    print("\n5. 数据绑定问题:")
    print("   问题: 界面数据与模型数据不同步")
    print("   解决: 使用观察者模式或数据绑定框架")

# 运行常见问题演示
common_issues_solutions()

# 7. 学习建议和总结

# 7.1 学习路径

def learning_path():
    """GUI编程学习路径"""
    print("=== GUI编程学习路径 ===")
    
    learning_steps = [
        {
            "阶段": "基础入门",
            "内容": [
                "理解GUI编程概念",
                "掌握基本控件使用",
                "学习布局管理",
                "练习事件处理"
            ],
            "项目": "简单的表单应用"
        },
        {
            "阶段": "进阶应用",
            "内容": [
                "高级控件使用",
                "菜单和工具栏",
                "对话框设计",
                "数据展示控件"
            ],
            "项目": "数据管理应用"
        },
        {
            "阶段": "高级特性",
            "内容": [
                "自定义控件",
                "主题和样式",
                "多线程GUI",
                "插件架构"
            ],
            "项目": "完整的桌面应用"
        },
        {
            "阶段": "专业开发",
            "内容": [
                "性能优化",
                "跨平台部署",
                "用户体验设计",
                "测试和调试"
            ],
            "项目": "商业级应用"
        }
    ]
    
    for i, step in enumerate(learning_steps, 1):
        print(f"\n{i}. {step['阶段']}:")
        for content in step['内容']:
            print(f"   - {content}")
        print(f"   推荐项目: {step['项目']}")

# 运行学习路径演示
learning_path()

# 7.2 实践建议

def practice_suggestions():
    """实践建议"""
    print("=== 实践建议 ===")
    
    suggestions = {
        "项目练习": [
            "从简单项目开始,逐步增加复杂度",
            "模仿现有应用的界面设计",
            "关注用户体验和界面美观",
            "完成完整的项目周期"
        ],
        "代码质量": [
            "遵循编码规范和最佳实践",
            "编写清晰的注释和文档",
            "进行代码重构和优化",
            "使用版本控制管理代码"
        ],
        "学习资源": [
            "官方文档和教程",
            "开源项目源码学习",
            "技术博客和视频教程",
            "参与社区讨论和交流"
        ],
        "技能拓展": [
            "学习其他GUI框架(PyQt, wxPython)",
            "了解Web前端技术",
            "掌握设计工具和原型制作",
            "学习移动应用开发"
        ]
    }
    
    for category, items in suggestions.items():
        print(f"\n{category}:")
        for item in items:
            print(f"  • {item}")

# 运行实践建议演示
practice_suggestions()

# 7.3 总结

def chapter_summary():
    """本章总结"""
    print("=== 第17天学习总结 ===")
    
    summary_points = {
        "核心概念": [
            "GUI编程基础和事件驱动模型",
            "Tkinter框架的基本使用",
            "控件、布局和事件处理",
            "用户界面设计原则"
        ],
        "重要技能": [
            "基本控件的使用和配置",
            "布局管理器的选择和应用",
            "事件处理和用户交互",
            "菜单、对话框等高级组件"
        ],
        "实际应用": [
            "计算器应用开发",
            "文本编辑器实现",
            "数据展示和可视化",
            "完整桌面应用构建"
        ],
        "最佳实践": [
            "代码组织和模块化设计",
            "用户体验优化",
            "性能和兼容性考虑",
            "错误处理和调试技巧"
        ]
    }
    
    for category, points in summary_points.items():
        print(f"\n{category}:")
        for point in points:
            print(f"  ✓ {point}")
    
    print("\n下一步学习方向:")
    print("  • 深入学习高级GUI框架(PyQt/PySide)")
    print("  • 探索Web应用开发(Flask/Django)")
    print("  • 学习移动应用开发")
    print("  • 掌握数据可视化技术")
    
    print("\n恭喜完成第17天的学习!")
    print("你已经掌握了Python GUI编程的基础知识和实践技能。")
    print("继续练习和探索,构建更复杂和实用的桌面应用程序!")

# 运行总结
chapter_summary()

通过第17天的学习,你已经全面掌握了Python图形界面编程的核心概念和实践技能。从基础的控件使用到复杂的应用开发,从事件处理到用户体验设计,这些知识将为你开发桌面应用程序奠定坚实的基础。

记住,GUI编程不仅仅是技术实现,更重要的是理解用户需求,设计直观易用的界面。继续练习和探索,你将能够创建出功能强大、界面美观的桌面应用程序!