打造现代化雷达电子对抗仿真界面 第一篇:tkinter/ttk 现代化高级技巧与复杂布局系统设计

摘要

本文将深入探讨tkinter/ttk在复杂UI设计中的高级应用,通过构建专业级雷达电子对抗仿真界面,展示Python标准GUI库在现代应用开发中的强大能力。内容涵盖高级布局管理、自定义控件开发、主题引擎设计等核心技术,为后续专业系统实现奠定基础。


目录

  1. 引言:为什么选择tkinter/ttk?

  2. tkinter/ttk核心架构深度解析

  3. 现代化复杂布局系统设计

  4. 自定义控件的开发与应用

  5. 主题引擎与皮肤系统实现

  6. 数据绑定与MVC模式实践

  7. 多线程与异步UI更新

  8. 实战:构建可复用的布局框架

  9. 性能优化与最佳实践

  10. 总结与展望


1. 引言:为什么选择tkinter/ttk?

在开始深入技术细节之前,我们需要明确一个核心问题:在众多Python GUI框架中,为什么选择tkinter/ttk来构建专业的雷达电子对抗仿真系统?

1.1 tkinter/ttk的独特优势

1.2 雷达电子对抗仿真的UI需求分析

雷达电子对抗仿真系统对UI有特殊要求:

  1. 实时性要求高:需要快速响应用户操作和数据显示

  2. 布局复杂:多视图、多面板、动态调整

  3. 数据可视化:雷达图、频谱图、波形图等专业图表

  4. 专业交互:参数设置、状态监控、告警提示

  5. 主题适配:日间/夜间模式切换,适应不同操作环境

1.3 本系列博客的技术路线

2. tkinter/ttk核心架构深度解析

2.1 tkinter与ttk的关系

python 复制代码
"""
tkinter_ttk_architecture.py

展示tkinter与ttk的架构关系和工作原理
"""
import tkinter as tk
from tkinter import ttk
import sys

class ArchitectureDemo:
    """tkinter/ttk架构演示"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("tkinter/ttk架构深度解析")
        self.root.geometry("1000x700")
        
        # 创建架构说明界面
        self.create_architecture_view()
        
    def create_architecture_view(self):
        """创建架构说明界面"""
        # 使用PanedWindow分割左右视图
        main_pane = ttk.PanedWindow(self.root, orient=tk.HORIZONTAL)
        main_pane.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 左侧:理论说明
        left_frame = ttk.Frame(main_pane)
        self.create_theory_panel(left_frame)
        main_pane.add(left_frame, weight=1)
        
        # 右侧:代码演示
        right_frame = ttk.Frame(main_pane)
        self.create_code_panel(right_frame)
        main_pane.add(right_frame, weight=2)
        
    def create_theory_panel(self, parent):
        """创建理论说明面板"""
        # 标题
        title_label = ttk.Label(
            parent, 
            text="tkinter/ttk 架构层次", 
            font=("微软雅黑", 16, "bold"),
            foreground="#2C3E50"
        )
        title_label.pack(pady=10)
        
        # 架构图说明
        architecture_text = """
tkinter/ttk 采用分层架构设计:

1. 应用层 (Application Layer)
   ├── 窗口管理
   ├── 事件循环
   └── 主线程调度

2. 控件层 (Widget Layer)
   ├── tkinter 基础控件
   │   ├── Frame, Label, Button
   │   ├── Canvas, Text, Entry
   │   └── Listbox, Menu, Scrollbar
   ├── ttk 主题化控件
   │   ├── Combobox, Notebook
   │   ├── Progressbar, Treeview
   │   └── Separator, Sizegrip
   └── 自定义控件
       ├── 组合控件
       ├── 数据可视化控件
       └── 专业领域控件

3. 渲染层 (Rendering Layer)
   ├── Tk 原生渲染
   ├── 主题引擎
   └── 样式系统

4. 平台层 (Platform Layer)
   ├── Windows API
   ├── X11 (Linux)
   └── Cocoa (macOS)
"""
        
        text_widget = tk.Text(
            parent,
            wrap=tk.WORD,
            font=("Consolas", 10),
            bg="#F8F9FA",
            relief=tk.FLAT,
            height=20
        )
        text_widget.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        text_widget.insert("1.0", architecture_text)
        text_widget.config(state=tk.DISABLED)  # 设置为只读
        
        # 添加关键特性说明
        features_frame = ttk.LabelFrame(parent, text="关键特性对比", padding=10)
        features_frame.pack(fill=tk.X, padx=10, pady=10)
        
        features = [
            ("原生支持", "tkinter", "Python标准库,无需额外依赖"),
            ("主题化", "ttk", "支持系统主题和自定义主题"),
            ("高性能", "Canvas", "原生绘制,适合实时图形"),
            ("跨平台", "Tk", "Windows, macOS, Linux 全支持"),
            ("可访问性", "tkinter", "支持屏幕阅读器等辅助技术")
        ]
        
        for feature, module, description in features:
            frame = ttk.Frame(features_frame)
            frame.pack(fill=tk.X, pady=2)
            
            ttk.Label(frame, text=feature, width=12, 
                     font=("微软雅黑", 9, "bold")).pack(side=tk.LEFT)
            ttk.Label(frame, text=module, width=10,
                     foreground="#2980B9").pack(side=tk.LEFT, padx=5)
            ttk.Label(frame, text=description, 
                     foreground="#7F8C8D").pack(side=tk.LEFT)
    
    def create_code_panel(self, parent):
        """创建代码演示面板"""
        notebook = ttk.Notebook(parent)
        notebook.pack(fill=tk.BOTH, expand=True)
        
        # 标签页1:基础控件对比
        tab1 = ttk.Frame(notebook)
        self.create_basic_widgets_tab(tab1)
        notebook.add(tab1, text="基础控件对比")
        
        # 标签页2:样式系统
        tab2 = ttk.Frame(notebook)
        self.create_style_system_tab(tab2)
        notebook.add(tab2, text="样式系统")
        
        # 标签页3:事件处理
        tab3 = ttk.Frame(notebook)
        self.create_event_system_tab(tab3)
        notebook.add(tab3, text="事件处理")
        
    def create_basic_widgets_tab(self, parent):
        """创建基础控件对比标签页"""
        # 使用Frame分组
        left_frame = ttk.Frame(parent)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        right_frame = ttk.Frame(parent)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # tkinter 基础控件
        tk_group = ttk.LabelFrame(left_frame, text="tkinter 基础控件", padding=10)
        tk_group.pack(fill=tk.BOTH, expand=True)
        
        # 添加示例控件
        widgets = [
            ("Button", tk.Button(tk_group, text="标准按钮")),
            ("Label", tk.Label(tk_group, text="标准标签", bg="white", relief=tk.RAISED)),
            ("Entry", tk.Entry(tk_group)),
            ("Canvas", tk.Canvas(tk_group, width=200, height=100, bg="#ECF0F1"))
        ]
        
        for name, widget in widgets:
            ttk.Label(tk_group, text=name + ":").pack(anchor=tk.W, pady=2)
            widget.pack(fill=tk.X, pady=5)
        
        # ttk 主题控件
        ttk_group = ttk.LabelFrame(right_frame, text="ttk 主题控件", padding=10)
        ttk_group.pack(fill=tk.BOTH, expand=True)
        
        # 添加ttk控件
        ttk_widgets = [
            ("Button", ttk.Button(ttk_group, text="主题按钮")),
            ("Label", ttk.Label(ttk_group, text="主题标签")),
            ("Entry", ttk.Entry(ttk_group)),
            ("Combobox", ttk.Combobox(ttk_group, values=["选项1", "选项2", "选项3"]))
        ]
        
        for name, widget in ttk_widgets:
            ttk.Label(ttk_group, text=name + ":").pack(anchor=tk.W, pady=2)
            widget.pack(fill=tk.X, pady=5)
            
        # 设置Combobox默认值
        ttk_widgets[3][1].set("选项1")
    
    def create_style_system_tab(self, parent):
        """创建样式系统标签页"""
        # 样式演示区域
        demo_frame = ttk.Frame(parent)
        demo_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 创建样式管理器
        style = ttk.Style()
        
        # 定义不同样式
        styles_config = [
            ("default.TButton", "默认样式"),
            ("primary.TButton", {"background": "#3498DB", "foreground": "white"}, "主色调"),
            ("success.TButton", {"background": "#2ECC71", "foreground": "white"}, "成功色调"),
            ("warning.TButton", {"background": "#F39C12", "foreground": "white"}, "警告色调"),
            ("danger.TButton", {"background": "#E74C3C", "foreground": "white"}, "危险色调")
        ]
        
        # 应用样式
        for style_name, style_params, description in styles_config:
            if isinstance(style_params, dict):
                style.configure(style_name, **style_params)
            
            frame = ttk.Frame(demo_frame)
            frame.pack(fill=tk.X, pady=5)
            
            ttk.Label(frame, text=description, width=10).pack(side=tk.LEFT, padx=5)
            ttk.Button(frame, text=description, style=style_name).pack(side=tk.LEFT)
            
            # 显示样式代码
            code_text = f"style.configure('{style_name}', {style_params})"
            ttk.Label(frame, text=code_text, font=("Consolas", 8), 
                     foreground="#7F8C8D").pack(side=tk.RIGHT, padx=10)
    
    def create_event_system_tab(self, parent):
        """创建事件处理标签页"""
        # 事件演示区域
        canvas = tk.Canvas(parent, bg="white", height=300)
        canvas.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 事件日志
        log_frame = ttk.Frame(parent)
        log_frame.pack(fill=tk.X, padx=10, pady=5)
        
        ttk.Label(log_frame, text="事件日志:").pack(anchor=tk.W)
        
        log_text = tk.Text(log_frame, height=8, font=("Consolas", 9))
        log_scroll = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=log_text.yview)
        log_text.configure(yscrollcommand=log_scroll.set)
        
        log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        log_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 记录事件
        def log_event(event, event_type):
            import datetime
            timestamp = datetime.datetime.now().strftime("%H:%M:%S.%f")[:-3]
            message = f"[{timestamp}] {event_type}: ({event.x}, {event.y})\n"
            log_text.insert(tk.END, message)
            log_text.see(tk.END)
        
        # 绑定事件
        def on_click(event):
            canvas.create_oval(event.x-5, event.y-5, event.x+5, event.y+5, 
                             fill="red", outline="black")
            log_event(event, "单击")
        
        def on_double_click(event):
            canvas.create_rectangle(event.x-10, event.y-10, event.x+10, event.y+10,
                                  fill="blue", outline="black")
            log_event(event, "双击")
        
        def on_drag(event):
            canvas.create_line(event.x, event.y, event.x+1, event.y+1, 
                             fill="green", width=2)
            log_event(event, "拖动")
        
        # 绑定事件到Canvas
        canvas.bind("<Button-1>", on_click)
        canvas.bind("<Double-Button-1>", on_double_click)
        canvas.bind("<B1-Motion>", on_drag)
        
        # 事件说明
        info_text = """
事件绑定说明:
- 单击左键: 绘制红色圆点
- 双击左键: 绘制蓝色方块
- 拖动左键: 绘制绿色线条

事件对象包含的属性:
- x, y: 事件坐标
- x_root, y_root: 屏幕坐标
- state: 修饰键状态
- keysym: 按键符号
        """
        
        info_label = ttk.Label(parent, text=info_text, justify=tk.LEFT,
                              font=("Consolas", 9), background="#F8F9FA")
        info_label.pack(fill=tk.X, padx=10, pady=5)

if __name__ == "__main__":
    root = tk.Tk()
    app = ArchitectureDemo(root)
    
    # 窗口居中
    root.update_idletasks()
    width = root.winfo_width()
    height = root.winfo_height()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = (screen_width - width) // 2
    y = (screen_height - height) // 2
    root.geometry(f'{width}x{height}+{x}+{y}')
    
    root.mainloop()

2.2 事件处理机制深度解析

3. 现代化复杂布局系统设计

3.1 布局管理器对比分析

python 复制代码
"""
layout_managers_comparison.py

三种布局管理器的详细对比和高级用法
"""
import tkinter as tk
from tkinter import ttk

class LayoutComparison:
    """布局管理器对比演示"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("布局管理器深度对比")
        self.root.geometry("1200x800")
        
        self.setup_styles()
        self.create_interface()
        
    def setup_styles(self):
        """设置样式"""
        style = ttk.Style()
        
        # 自定义样式
        style.configure("Title.TLabel", 
                       font=("微软雅黑", 16, "bold"),
                       foreground="#2C3E50")
        
        style.configure("Section.TLabelframe.Label",
                       font=("微软雅黑", 12, "bold"),
                       foreground="#34495E")
        
        style.configure("Code.TLabel",
                       font=("Consolas", 10),
                       background="#2C3E50",
                       foreground="#ECF0F1",
                       padding=5)
    
    def create_interface(self):
        """创建主界面"""
        notebook = ttk.Notebook(self.root)
        notebook.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 三个标签页
        self.create_pack_tab(notebook)
        self.create_grid_tab(notebook)
        self.create_place_tab(notebook)
        self.create_combined_tab(notebook)
        
    def create_pack_tab(self, notebook):
        """创建pack布局演示标签页"""
        frame = ttk.Frame(notebook)
        notebook.add(frame, text="Pack布局管理器")
        
        # 理论说明
        theory_frame = ttk.LabelFrame(frame, text="Pack布局原理", style="Section.TLabelframe")
        theory_frame.pack(fill=tk.X, padx=10, pady=5)
        
        theory_text = """
Pack布局管理器采用块状布局方式,按照添加顺序排列控件。

核心参数:
- side: 停靠方向 (TOP, BOTTOM, LEFT, RIGHT)
- fill: 填充方式 (NONE, X, Y, BOTH)
- expand: 是否扩展空间
- anchor: 对齐方式
- padx/pady: 外部间距
- ipadx/ipady: 内部间距

特点:
1. 简单易用,适合简单布局
2. 自动处理控件大小和位置
3. 支持嵌套使用
4. 响应式调整有限
        """
        
        theory_label = ttk.Label(theory_frame, text=theory_text, 
                                justify=tk.LEFT, wraplength=600)
        theory_label.pack(padx=10, pady=10)
        
        # 示例演示
        demo_frame = ttk.LabelFrame(frame, text="Pack布局示例", style="Section.TLabelframe")
        demo_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 创建演示区域
        self.create_pack_demo(demo_frame)
        
    def create_pack_demo(self, parent):
        """创建pack布局演示"""
        # 控制面板
        control_frame = ttk.Frame(parent)
        control_frame.pack(fill=tk.X, pady=5)
        
        # 方向选择
        ttk.Label(control_frame, text="停靠方向:").pack(side=tk.LEFT, padx=5)
        side_var = tk.StringVar(value="top")
        side_combo = ttk.Combobox(control_frame, textvariable=side_var,
                                 values=["top", "bottom", "left", "right"],
                                 state="readonly", width=10)
        side_combo.pack(side=tk.LEFT, padx=5)
        
        # 填充方式
        ttk.Label(control_frame, text="填充方式:").pack(side=tk.LEFT, padx=5)
        fill_var = tk.StringVar(value="none")
        fill_combo = ttk.Combobox(control_frame, textvariable=fill_var,
                                 values=["none", "x", "y", "both"],
                                 state="readonly", width=10)
        fill_combo.pack(side=tk.LEFT, padx=5)
        
        # 演示面板
        demo_panel = ttk.Frame(parent, relief=tk.SUNKEN, borderwidth=2)
        demo_panel.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 添加示例控件
        colors = ["#E74C3C", "#3498DB", "#2ECC71", "#F39C12", "#9B59B6"]
        self.pack_widgets = []
        
        for i, color in enumerate(colors):
            frame = tk.Frame(demo_panel, bg=color, width=100, height=50)
            label = tk.Label(frame, text=f"控件{i+1}", bg=color, fg="white")
            label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
            self.pack_widgets.append(frame)
        
        # 默认布局
        self.apply_pack_layout("top", "none")
        
        # 更新布局函数
        def update_layout():
            side = side_var.get()
            fill = fill_var.get()
            self.apply_pack_layout(side, fill)
        
        side_combo.bind("<<ComboboxSelected>>", lambda e: update_layout())
        fill_combo.bind("<<ComboboxSelected>>", lambda e: update_layout())
        
        # 添加控制按钮
        btn_frame = ttk.Frame(control_frame)
        btn_frame.pack(side=tk.RIGHT, padx=10)
        
        ttk.Button(btn_frame, text="添加控件", 
                  command=self.add_pack_widget).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_frame, text="移除控件", 
                  command=self.remove_pack_widget).pack(side=tk.LEFT, padx=2)
        
    def apply_pack_layout(self, side, fill):
        """应用pack布局"""
        # 移除所有控件
        for widget in self.pack_widgets:
            widget.pack_forget()
        
        # 重新应用布局
        for widget in self.pack_widgets:
            widget.pack(side=side, fill=fill, expand=True, 
                       padx=2, pady=2, ipadx=5, ipady=5)
    
    def add_pack_widget(self):
        """添加pack控件"""
        if len(self.pack_widgets) >= 8:
            return
            
        colors = ["#1ABC9C", "#34495E", "#E67E22", "#95A5A6"]
        color = colors[len(self.pack_widgets) % 4]
        
        frame = tk.Frame(self.pack_widgets[0].master, bg=color, width=100, height=50)
        label = tk.Label(frame, text=f"控件{len(self.pack_widgets)+1}", 
                        bg=color, fg="white")
        label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
        
        self.pack_widgets.append(frame)
        self.apply_pack_layout("top", "none")
    
    def remove_pack_widget(self):
        """移除pack控件"""
        if len(self.pack_widgets) > 1:
            widget = self.pack_widgets.pop()
            widget.destroy()
            self.apply_pack_layout("top", "none")
    
    def create_grid_tab(self, notebook):
        """创建grid布局演示标签页"""
        frame = ttk.Frame(notebook)
        notebook.add(frame, text="Grid布局管理器")
        
        # 理论说明
        theory_frame = ttk.LabelFrame(frame, text="Grid布局原理", style="Section.TLabelframe")
        theory_frame.pack(fill=tk.X, padx=10, pady=5)
        
        theory_text = """
Grid布局管理器采用表格布局方式,将容器划分为行和列。

核心参数:
- row/column: 行列位置 (从0开始)
- rowspan/columnspan: 行列跨度
- sticky: 拉伸对齐 (N, S, E, W, NE, NW, SE, SW, CENTER)
- padx/pady: 外部间距
- ipadx/ipady: 内部间距

特点:
1. 灵活强大,适合复杂布局
2. 精确控制控件位置
3. 支持行列权重分配
4. 自动调整单元格大小
        """
        
        theory_label = ttk.Label(theory_frame, text=theory_text, 
                                justify=tk.LEFT, wraplength=600)
        theory_label.pack(padx=10, pady=10)
        
        # 示例演示
        demo_frame = ttk.LabelFrame(frame, text="Grid布局示例", style="Section.TLabelframe")
        demo_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 创建网格布局演示
        self.create_grid_demo(demo_frame)
        
    def create_grid_demo(self, parent):
        """创建grid布局演示"""
        # 控制面板
        control_frame = ttk.Frame(parent)
        control_frame.grid(row=0, column=0, columnspan=3, sticky="ew", pady=5)
        
        # 行列数控制
        ttk.Label(control_frame, text="行数:").pack(side=tk.LEFT, padx=5)
        rows_var = tk.IntVar(value=3)
        rows_spin = ttk.Spinbox(control_frame, from_=1, to=10, 
                               textvariable=rows_var, width=5)
        rows_spin.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(control_frame, text="列数:").pack(side=tk.LEFT, padx=5)
        cols_var = tk.IntVar(value=3)
        cols_spin = ttk.Spinbox(control_frame, from_=1, to=10,
                               textvariable=cols_var, width=5)
        cols_spin.pack(side=tk.LEFT, padx=5)
        
        # 演示面板
        demo_panel = ttk.Frame(parent, relief=tk.SUNKEN, borderwidth=2)
        demo_panel.grid(row=1, column=0, columnspan=3, 
                       sticky="nsew", padx=10, pady=10)
        
        # 配置权重
        parent.grid_rowconfigure(1, weight=1)
        parent.grid_columnconfigure(0, weight=1)
        parent.grid_columnconfigure(1, weight=1)
        parent.grid_columnconfigure(2, weight=1)
        
        # 创建网格
        self.grid_widgets = []
        self.demo_panel = demo_panel
        
        def update_grid():
            """更新网格布局"""
            # 清除现有控件
            for widget in self.grid_widgets:
                widget.destroy()
            self.grid_widgets.clear()
            
            rows = rows_var.get()
            cols = cols_var.get()
            
            # 创建新网格
            for r in range(rows):
                for c in range(cols):
                    # 计算颜色
                    hue = (r * cols + c) / (rows * cols)
                    color = self.hsv_to_rgb(hue, 0.7, 0.8)
                    
                    frame = tk.Frame(demo_panel, bg=color, 
                                    width=80, height=60)
                    frame.grid(row=r, column=c, 
                              sticky="nsew", padx=2, pady=2)
                    
                    label = tk.Label(frame, text=f"({r},{c})", 
                                   bg=color, fg="white")
                    label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
                    
                    # 配置行列权重
                    demo_panel.grid_rowconfigure(r, weight=1)
                    demo_panel.grid_columnconfigure(c, weight=1)
                    
                    self.grid_widgets.append(frame)
        
        # 初始布局
        update_grid()
        
        # 绑定事件
        rows_spin.bind("<<Increment>>", lambda e: update_grid())
        rows_spin.bind("<<Decrement>>", lambda e: update_grid())
        cols_spin.bind("<<Increment>>", lambda e: update_grid())
        cols_spin.bind("<<Decrement>>", lambda e: update_grid())
        
        # 添加控制按钮
        btn_frame = ttk.Frame(control_frame)
        btn_frame.pack(side=tk.RIGHT, padx=10)
        
        ttk.Button(btn_frame, text="更新网格", command=update_grid).pack(side=tk.LEFT, padx=2)
        
    def hsv_to_rgb(self, h, s, v):
        """HSV转RGB"""
        import colorsys
        r, g, b = colorsys.hsv_to_rgb(h, s, v)
        return f"#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}"
    
    def create_place_tab(self, notebook):
        """创建place布局演示标签页"""
        frame = ttk.Frame(notebook)
        notebook.add(frame, text="Place布局管理器")
        
        # 理论说明
        theory_frame = ttk.LabelFrame(frame, text="Place布局原理", style="Section.TLabelframe")
        theory_frame.pack(fill=tk.X, padx=10, pady=5)
        
        theory_text = """
Place布局管理器采用绝对定位方式,通过坐标精确控制控件位置。

核心参数:
- x, y: 绝对坐标 (像素)
- relx, rely: 相对坐标 (0.0-1.0)
- anchor: 锚点位置
- width, height: 绝对大小
- relwidth, relheight: 相对大小

特点:
1. 精确控制,适合特殊布局需求
2. 性能最佳,无布局计算开销
3. 不支持响应式调整
4. 维护成本高
        """
        
        theory_label = ttk.Label(theory_frame, text=theory_text, 
                                justify=tk.LEFT, wraplength=600)
        theory_label.pack(padx=10, pady=10)
        
        # 示例演示
        demo_frame = ttk.LabelFrame(frame, text="Place布局示例", style="Section.TLabelframe")
        demo_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 创建place布局演示
        self.create_place_demo(demo_frame)
        
    def create_place_demo(self, parent):
        """创建place布局演示"""
        # 控制面板
        control_frame = ttk.Frame(parent)
        control_frame.pack(fill=tk.X, pady=5)
        
        # 坐标控制
        ttk.Label(control_frame, text="X坐标:").pack(side=tk.LEFT, padx=5)
        x_var = tk.DoubleVar(value=0.5)
        x_scale = ttk.Scale(control_frame, from_=0, to=1, 
                           variable=x_var, orient=tk.HORIZONTAL, length=200)
        x_scale.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(control_frame, text="Y坐标:").pack(side=tk.LEFT, padx=5)
        y_var = tk.DoubleVar(value=0.5)
        y_scale = ttk.Scale(control_frame, from_=0, to=1,
                           variable=y_var, orient=tk.HORIZONTAL, length=200)
        y_scale.pack(side=tk.LEFT, padx=5)
        
        # 演示面板
        demo_panel = tk.Canvas(parent, bg="white", highlightthickness=0)
        demo_panel.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 创建可拖动控件
        self.place_widget = tk.Frame(demo_panel, bg="#E74C3C", 
                                    width=100, height=100)
        
        # 添加标签
        label = tk.Label(self.place_widget, text="可拖动控件", 
                        bg="#E74C3C", fg="white", font=("微软雅黑", 10))
        label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
        
        # 初始位置
        self.place_widget.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
        
        # 拖动功能
        def start_drag(event):
            self.place_widget._drag_data = {"x": event.x, "y": event.y}
            
        def stop_drag(event):
            self.place_widget._drag_data = None
            
        def do_drag(event):
            if hasattr(self.place_widget, "_drag_data"):
                dx = event.x - self.place_widget._drag_data["x"]
                dy = event.y - self.place_widget._drag_data["y"]
                
                # 获取当前相对位置
                info = self.place_widget.place_info()
                relx = float(info["relx"])
                rely = float(info["rely"])
                
                # 计算新位置
                panel_width = demo_panel.winfo_width()
                panel_height = demo_panel.winfo_height()
                
                if panel_width > 0 and panel_height > 0:
                    new_relx = relx + dx / panel_width
                    new_rely = rely + dy / panel_height
                    
                    # 限制在范围内
                    new_relx = max(0, min(1, new_relx))
                    new_rely = max(0, min(1, new_rely))
                    
                    # 更新位置
                    self.place_widget.place(relx=new_relx, rely=new_rely, anchor=tk.CENTER)
                    
                    # 更新滑块
                    x_var.set(new_relx)
                    y_var.set(new_rely)
                
                self.place_widget._drag_data = {"x": event.x, "y": event.y}
        
        # 绑定事件
        self.place_widget.bind("<Button-1>", start_drag)
        self.place_widget.bind("<B1-Motion>", do_drag)
        self.place_widget.bind("<ButtonRelease-1>", stop_drag)
        
        # 滑块控制
        def update_position(event=None):
            relx = x_var.get()
            rely = y_var.get()
            self.place_widget.place(relx=relx, rely=rely, anchor=tk.CENTER)
        
        x_scale.configure(command=lambda v: update_position())
        y_scale.configure(command=lambda v: update_position())
        
    def create_combined_tab(self, notebook):
        """创建混合布局演示标签页"""
        frame = ttk.Frame(notebook)
        notebook.add(frame, text="混合布局实战")
        
        # 创建实战示例:仪表板布局
        self.create_dashboard_demo(frame)
        
    def create_dashboard_demo(self, parent):
        """创建仪表板布局演示"""
        # 主容器 - 使用grid布局
        main_container = ttk.Frame(parent)
        main_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 配置网格权重
        for i in range(3):
            main_container.grid_rowconfigure(i, weight=1)
        for i in range(3):
            main_container.grid_columnconfigure(i, weight=1)
        
        # 1. 顶部导航栏 (grid, 跨3列)
        header = ttk.Frame(main_container, relief=tk.RAISED, borderwidth=1)
        header.grid(row=0, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
        
        # 导航栏内部使用pack布局
        ttk.Label(header, text="雷达电子对抗仿真系统", 
                 font=("微软雅黑", 14, "bold")).pack(side=tk.LEFT, padx=10)
        
        # 导航按钮使用pack
        nav_frame = ttk.Frame(header)
        nav_frame.pack(side=tk.RIGHT, padx=10)
        
        nav_buttons = ["文件", "编辑", "视图", "工具", "帮助"]
        for text in nav_buttons:
            ttk.Button(nav_frame, text=text, width=8).pack(side=tk.LEFT, padx=2)
        
        # 2. 左侧边栏 (grid, 占1列2行)
        sidebar = ttk.Frame(main_container, relief=tk.SUNKEN, borderwidth=1)
        sidebar.grid(row=1, column=0, rowspan=2, sticky="nsew", padx=5, pady=5)
        
        # 侧边栏使用pack布局
        ttk.Label(sidebar, text="系统状态", font=("微软雅黑", 11, "bold")).pack(pady=10)
        
        status_items = [
            ("雷达状态", "在线", "#2ECC71"),
            ("数据链路", "正常", "#2ECC71"),
            ("干扰设备", "就绪", "#F39C12"),
            ("告警系统", "静默", "#3498DB")
        ]
        
        for name, status, color in status_items:
            frame = ttk.Frame(sidebar)
            frame.pack(fill=tk.X, padx=10, pady=5)
            
            ttk.Label(frame, text=name).pack(side=tk.LEFT)
            ttk.Label(frame, text=status, foreground=color, 
                     font=("Consolas", 9, "bold")).pack(side=tk.RIGHT)
        
        # 3. 中央主区域 (grid, 占1行2列)
        main_area = ttk.Frame(main_container, relief=tk.SUNKEN, borderwidth=1)
        main_area.grid(row=1, column=1, columnspan=2, sticky="nsew", padx=5, pady=5)
        
        # 主区域使用place和grid混合布局
        
        # 雷达显示器 (place布局,用于精确定位)
        radar_frame = tk.Frame(main_area, bg="#1C2833")
        radar_frame.place(relx=0.5, rely=0.4, anchor=tk.CENTER, 
                         relwidth=0.8, relheight=0.7)
        
        # 绘制简单雷达
        canvas = tk.Canvas(radar_frame, bg="#1C2833", highlightthickness=0)
        canvas.pack(fill=tk.BOTH, expand=True)
        
        # 绘制雷达扫描线
        self.draw_radar(canvas)
        
        # 控制面板 (grid布局,底部固定高度)
        control_panel = ttk.Frame(main_area)
        control_panel.place(relx=0.5, rely=0.9, anchor=tk.CENTER, 
                           relwidth=0.9, relheight=0.15)
        
        # 控制按钮
        controls = ["启动", "暂停", "停止", "记录", "设置"]
        for i, text in enumerate(controls):
            ttk.Button(control_panel, text=text, width=10).grid(
                row=0, column=i, padx=5, pady=5, sticky="ew"
            )
            control_panel.grid_columnconfigure(i, weight=1)
        
        # 4. 底部状态栏 (grid, 跨3列)
        statusbar = ttk.Frame(main_container, relief=tk.SUNKEN, borderwidth=1)
        statusbar.grid(row=3, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
        
        # 状态栏使用pack布局
        ttk.Label(statusbar, text="就绪").pack(side=tk.LEFT, padx=10)
        
        # 系统信息
        import datetime
        time_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        ttk.Label(statusbar, text=f"系统时间: {time_str}").pack(side=tk.RIGHT, padx=10)
        
        # 内存使用模拟
        import psutil
        memory = psutil.virtual_memory()
        memory_text = f"内存: {memory.percent}%"
        ttk.Label(statusbar, text=memory_text).pack(side=tk.RIGHT, padx=10)
    
    def draw_radar(self, canvas):
        """绘制雷达图"""
        def update_radar():
            # 清除画布
            canvas.delete("all")
            
            width = canvas.winfo_width()
            height = canvas.winfo_height()
            
            if width < 10 or height < 10:
                canvas.after(100, update_radar)
                return
            
            center_x = width // 2
            center_y = height // 2
            radius = min(center_x, center_y) - 20
            
            # 绘制同心圆
            for r in range(radius, 0, -radius//5):
                canvas.create_oval(
                    center_x - r, center_y - r,
                    center_x + r, center_y + r,
                    outline="#2ECC71", width=1
                )
            
            # 绘制坐标轴
            canvas.create_line(
                center_x, center_y - radius,
                center_x, center_y + radius,
                fill="#2ECC71", width=2
            )
            canvas.create_line(
                center_x - radius, center_y,
                center_x + radius, center_y,
                fill="#2ECC71", width=2
            )
            
            # 绘制扫描线
            import time
            current_time = time.time()
            angle = (current_time * 50) % 360
            rad = angle * 3.14159 / 180
            
            end_x = center_x + radius * math.sin(rad)
            end_y = center_y - radius * math.cos(rad)
            
            canvas.create_line(
                center_x, center_y, end_x, end_y,
                fill="#E74C3C", width=2
            )
            
            # 绘制随机目标
            import random
            for _ in range(random.randint(3, 8)):
                target_angle = random.uniform(0, 2 * 3.14159)
                target_dist = random.uniform(0.3, 0.9) * radius

3.2 高级布局模式:MVC架构实现

python 复制代码
"""
advanced_layout_framework.py

基于MVC模式的高级布局框架实现
"""
import tkinter as tk
from tkinter import ttk
from abc import ABC, abstractmethod
from typing import Dict, List, Any, Optional
import json

class LayoutManager:
    """布局管理器基类"""
    
    def __init__(self):
        self.widgets = {}
        self.layout_config = {}
        
    def add_widget(self, name: str, widget: tk.Widget, **config):
        """添加控件"""
        self.widgets[name] = {
            'widget': widget,
            'config': config
        }
        
    def apply_layout(self, container):
        """应用布局"""
        raise NotImplementedError("子类必须实现此方法")
        
    def save_layout(self, filename: str):
        """保存布局配置"""
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(self.layout_config, f, indent=2, ensure_ascii=False)
            
    def load_layout(self, filename: str):
        """加载布局配置"""
        with open(filename, 'r', encoding='utf-8') as f:
            self.layout_config = json.load(f)

class GridLayoutManager(LayoutManager):
    """网格布局管理器"""
    
    def __init__(self, rows: int = 1, cols: int = 1):
        super().__init__()
        self.rows = rows
        self.cols = cols
        self.row_weights = {}
        self.column_weights = {}
        
    def set_row_weight(self, row: int, weight: int):
        """设置行权重"""
        self.row_weights[row] = weight
        
    def set_column_weight(self, col: int, weight: int):
        """设置列权重"""
        self.column_weights[col] = weight
        
    def apply_layout(self, container):
        """应用网格布局"""
        # 配置行列权重
        for row, weight in self.row_weights.items():
            container.grid_rowconfigure(row, weight=weight)
            
        for col, weight in self.column_weights.items():
            container.grid_columnconfigure(col, weight=weight)
            
        # 布置控件
        for name, widget_info in self.widgets.items():
            widget = widget_info['widget']
            config = widget_info['config']
            widget.grid(**config, in_=container)

class ResponsiveLayoutManager(LayoutManager):
    """响应式布局管理器"""
    
    def __init__(self, breakpoints: Dict[str, int]):
        """
        breakpoints: 断点配置,如{'sm': 640, 'md': 768, 'lg': 1024}
        """
        super().__init__()
        self.breakpoints = breakpoints
        self.current_breakpoint = 'lg'
        self.layouts = {}  # 不同断点的布局配置
        
    def add_layout(self, breakpoint: str, layout_config: Dict):
        """添加断点布局配置"""
        self.layouts[breakpoint] = layout_config
        
    def apply_layout(self, container):
        """应用响应式布局"""
        width = container.winfo_width()
        
        # 确定当前断点
        self.current_breakpoint = 'lg'  # 默认
        for bp, bp_width in sorted(self.breakpoints.items(), 
                                  key=lambda x: x[1]):
            if width >= bp_width:
                self.current_breakpoint = bp
                
        # 应用对应布局
        layout_config = self.layouts.get(self.current_breakpoint, {})
        self._apply_specific_layout(container, layout_config)
        
    def _apply_specific_layout(self, container, layout_config: Dict):
        """应用特定布局"""
        # 清除所有控件的布局
        for widget in self.widgets.values():
            widget['widget'].grid_remove()
            widget['widget'].pack_forget()
            widget['widget'].place_forget()
            
        # 应用新布局
        for name, config in layout_config.items():
            if name in self.widgets:
                widget_info = self.widgets[name]
                widget = widget_info['widget']
                layout_type = config.get('type', 'grid')
                
                if layout_type == 'grid':
                    widget.grid(**config.get('config', {}), in_=container)
                elif layout_type == 'pack':
                    widget.pack(**config.get('config', {}), in_=container)
                elif layout_type == 'place':
                    widget.place(**config.get('config', {}), in_=container)

class View(ABC):
    """视图基类"""
    
    def __init__(self, parent):
        self.parent = parent
        self.frame = ttk.Frame(parent)
        self.layout_manager = None
        self.widgets = {}
        
    @abstractmethod
    def build_ui(self):
        """构建UI"""
        pass
        
    def set_layout_manager(self, layout_manager: LayoutManager):
        """设置布局管理器"""
        self.layout_manager = layout_manager
        
    def apply_layout(self):
        """应用布局"""
        if self.layout_manager:
            self.layout_manager.apply_layout(self.frame)
            
    def get_widget(self, name: str) -> Optional[tk.Widget]:
        """获取控件"""
        return self.widgets.get(name)

class Controller(ABC):
    """控制器基类"""
    
    def __init__(self, view: View, model=None):
        self.view = view
        self.model = model
        
    @abstractmethod
    def setup_events(self):
        """设置事件处理"""
        pass
        
    def update_view(self):
        """更新视图"""
        pass

class RadarSimulationView(View):
    """雷达仿真视图"""
    
    def build_ui(self):
        """构建雷达仿真UI"""
        # 创建控件
        self.widgets = {
            'radar_display': tk.Canvas(self.frame, bg='#1C2833'),
            'parameter_panel': ttk.Frame(self.frame),
            'control_panel': ttk.Frame(self.frame),
            'status_bar': ttk.Frame(self.frame, relief=tk.SUNKEN, borderwidth=1)
        }
        
        # 构建参数面板
        self._build_parameter_panel()
        
        # 构建控制面板
        self._build_control_panel()
        
        # 构建状态栏
        self._build_status_bar()
        
        # 设置响应式布局管理器
        layout_manager = ResponsiveLayoutManager({
            'sm': 640,
            'md': 800,
            'lg': 1024
        })
        
        # 为不同断点设置布局
        layout_manager.add_layout('sm', {
            'radar_display': {
                'type': 'grid',
                'config': {'row': 0, 'column': 0, 'sticky': 'nsew'}
            },
            'parameter_panel': {
                'type': 'grid', 
                'config': {'row': 1, 'column': 0, 'sticky': 'ew', 'pady': 5}
            },
            'control_panel': {
                'type': 'grid',
                'config': {'row': 2, 'column': 0, 'sticky': 'ew', 'pady': 5}
            },
            'status_bar': {
                'type': 'grid',
                'config': {'row': 3, 'column': 0, 'sticky': 'ew'}
            }
        })
        
        layout_manager.add_layout('md', {
            'radar_display': {
                'type': 'grid',
                'config': {'row': 0, 'column': 0, 'rowspan': 2, 'sticky': 'nsew'}
            },
            'parameter_panel': {
                'type': 'grid',
                'config': {'row': 0, 'column': 1, 'sticky': 'nsew', 'padx': 5}
            },
            'control_panel': {
                'type': 'grid',
                'config': {'row': 1, 'column': 1, 'sticky': 'nsew', 'padx': 5, 'pady': 5}
            },
            'status_bar': {
                'type': 'grid',
                'config': {'row': 2, 'column': 0, 'columnspan': 2, 'sticky': 'ew'}
            }
        })
        
        layout_manager.add_layout('lg', {
            'radar_display': {
                'type': 'grid',
                'config': {'row': 0, 'column': 0, 'rowspan': 3, 'sticky': 'nsew'}
            },
            'parameter_panel': {
                'type': 'grid',
                'config': {'row': 0, 'column': 1, 'sticky': 'nsew', 'padx': 5}
            },
            'control_panel': {
                'type': 'grid',
                'config': {'row': 1, 'column': 1, 'sticky': 'nsew', 'padx': 5, 'pady': 5}
            },
            'status_bar': {
                'type': 'grid',
                'config': {'row': 2, 'column': 0, 'columnspan': 2, 'sticky': 'ew'}
            }
        })
        
        # 添加控件到布局管理器
        for name, widget in self.widgets.items():
            layout_manager.add_widget(name, widget)
            
        self.set_layout_manager(layout_manager)
        
        # 配置网格权重
        self.frame.grid_rowconfigure(0, weight=1)
        self.frame.grid_rowconfigure(1, weight=1)
        self.frame.grid_rowconfigure(2, weight=0)  # 状态栏不扩展
        self.frame.grid_columnconfigure(0, weight=3)  # 雷达显示占3份
        self.frame.grid_columnconfigure(1, weight=1)  # 控制面板占1份
        
        # 绑定窗口大小变化事件
        self.frame.bind('<Configure>', self._on_resize)
        
    def _build_parameter_panel(self):
        """构建参数面板"""
        panel = self.widgets['parameter_panel']
        
        # 创建Notebook
        notebook = ttk.Notebook(panel)
        notebook.pack(fill=tk.BOTH, expand=True)
        
        # 雷达参数标签页
        radar_frame = ttk.Frame(notebook)
        self._create_radar_parameters(radar_frame)
        notebook.add(radar_frame, text='雷达参数')
        
        # 目标参数标签页
        target_frame = ttk.Frame(notebook)
        self._create_target_parameters(target_frame)
        notebook.add(target_frame, text='目标参数')
        
        # 环境参数标签页
        env_frame = ttk.Frame(notebook)
        self._create_environment_parameters(env_frame)
        notebook.add(env_frame, text='环境参数')
        
    def _create_radar_parameters(self, parent):
        """创建雷达参数设置"""
        # 使用网格布局
        row = 0
        
        # 频率设置
        ttk.Label(parent, text="工作频率 (MHz):").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        freq_var = tk.StringVar(value="3000")
        ttk.Entry(parent, textvariable=freq_var, width=15).grid(
            row=row, column=1, sticky=tk.EW, padx=5, pady=5
        )
        row += 1
        
        # 脉冲宽度
        ttk.Label(parent, text="脉冲宽度 (μs):").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        pulse_var = tk.StringVar(value="1.0")
        ttk.Entry(parent, textvariable=pulse_var, width=15).grid(
            row=row, column=1, sticky=tk.EW, padx=5, pady=5
        )
        row += 1
        
        # PRF
        ttk.Label(parent, text="PRF (Hz):").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        prf_var = tk.StringVar(value="1000")
        ttk.Entry(parent, textvariable=prf_var, width=15).grid(
            row=row, column=1, sticky=tk.EW, padx=5, pady=5
        )
        row += 1
        

        # 配置列权重
        parent.grid_columnconfigure(1, weight=1)
        parent.grid_rowconfigure(row, weight=1)
        
    def _create_target_parameters(self, parent):
        """创建目标参数设置"""
        row = 0
        
        # 目标数量
        ttk.Label(parent, text="目标数量:").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        target_count_var = tk.IntVar(value=3)
        ttk.Spinbox(parent, from_=1, to=20, textvariable=target_count_var, 
                   width=15).grid(row=row, column=1, sticky=tk.EW, padx=5, pady=5)
        row += 1
        
        # 目标RCS
        ttk.Label(parent, text="平均RCS (m²):").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        rcs_var = tk.DoubleVar(value=5.0)
        ttk.Entry(parent, textvariable=rcs_var, width=15).grid(
            row=row, column=1, sticky=tk.EW, padx=5, pady=5
        )
        row += 1
        
        # 目标速度
        ttk.Label(parent, text="目标速度 (m/s):").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        speed_var = tk.DoubleVar(value=300.0)
        ttk.Entry(parent, textvariable=speed_var, width=15).grid(
            row=row, column=1, sticky=tk.EW, padx=5, pady=5
        )
        row += 1
        
        # 配置列权重
        parent.grid_columnconfigure(1, weight=1)
        parent.grid_rowconfigure(row, weight=1)
        
    def _create_environment_parameters(self, parent):
        """创建环境参数设置"""
        row = 0
        
        # 环境杂波
        ttk.Label(parent, text="杂波强度:").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        clutter_var = tk.DoubleVar(value=0.5)
        ttk.Scale(parent, from_=0.0, to=1.0, variable=clutter_var,
                 orient=tk.HORIZONTAL).grid(row=row, column=1, 
                                           sticky=tk.EW, padx=5, pady=5)
        row += 1
        
        # 天气条件
        ttk.Label(parent, text="天气条件:").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        weather_var = tk.StringVar(value="晴朗")
        ttk.Combobox(parent, textvariable=weather_var,
                    values=["晴朗", "多云", "小雨", "大雨", "雾天"],
                    state="readonly", width=13).grid(row=row, column=1,
                                                    sticky=tk.EW, padx=5, pady=5)
        row += 1
        
        # 大气衰减
        ttk.Label(parent, text="大气衰减 (dB/km):").grid(
            row=row, column=0, sticky=tk.W, padx=5, pady=5
        )
        attenuation_var = tk.DoubleVar(value=0.2)
        ttk.Entry(parent, textvariable=attenuation_var, width=15).grid(
            row=row, column=1, sticky=tk.EW, padx=5, pady=5
        )
        row += 1
        
        # 配置列权重
        parent.grid_columnconfigure(1, weight=1)
        parent.grid_rowconfigure(row, weight=1)
        
    def _build_control_panel(self):
        """构建控制面板"""
        panel = self.widgets['control_panel']
        
        # 使用框架分组
        main_frame = ttk.Frame(panel)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 仿真控制
        control_frame = ttk.LabelFrame(main_frame, text="仿真控制", padding=10)
        control_frame.pack(fill=tk.X, pady=5)
        
        # 控制按钮
        buttons_frame = ttk.Frame(control_frame)
        buttons_frame.pack(fill=tk.X)
        
        button_texts = ["启动仿真", "暂停仿真", "停止仿真", "重置参数"]
        for i, text in enumerate(button_texts):
            btn = ttk.Button(buttons_frame, text=text)
            btn.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)
            
        # 仿真速度控制
        ttk.Label(control_frame, text="仿真速度:").pack(anchor=tk.W, pady=(10, 0))
        speed_var = tk.DoubleVar(value=1.0)
        ttk.Scale(control_frame, from_=0.1, to=5.0, variable=speed_var,
                 orient=tk.HORIZONTAL).pack(fill=tk.X, pady=5)
        
        # 数据显示控制
        display_frame = ttk.LabelFrame(main_frame, text="显示选项", padding=10)
        display_frame.pack(fill=tk.X, pady=5)
        
        display_options = [
            ("显示网格", tk.BooleanVar(value=True)),
            ("显示坐标轴", tk.BooleanVar(value=True)),
            ("显示目标轨迹", tk.BooleanVar(value=True)),
            ("实时更新", tk.BooleanVar(value=True))
        ]
        
        for text, var in display_options:
            cb = ttk.Checkbutton(display_frame, text=text, variable=var)
            cb.pack(anchor=tk.W, pady=2)
            
    def _build_status_bar(self):
        """构建状态栏"""
        status_bar = self.widgets['status_bar']
        
        # 左侧状态信息
        left_frame = ttk.Frame(status_bar)
        left_frame.pack(side=tk.LEFT, padx=10)
        
        self.status_label = ttk.Label(left_frame, text="就绪")
        self.status_label.pack(side=tk.LEFT)
        
        # 中间进度条
        center_frame = ttk.Frame(status_bar)
        center_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=10)
        
        self.progress_var = tk.DoubleVar(value=0.0)
        self.progress_bar = ttk.Progressbar(center_frame, 
                                          variable=self.progress_var,
                                          mode='determinate')
        self.progress_bar.pack(fill=tk.X)
        
        # 右侧系统信息
        right_frame = ttk.Frame(status_bar)
        right_frame.pack(side=tk.RIGHT, padx=10)
        
        import datetime
        time_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.time_label = ttk.Label(right_frame, text=f"时间: {time_str}")
        self.time_label.pack(side=tk.LEFT, padx=5)
        
        # 内存使用显示
        import psutil
        memory = psutil.virtual_memory()
        memory_text = f"内存: {memory.percent}%"
        self.memory_label = ttk.Label(right_frame, text=memory_text)
        self.memory_label.pack(side=tk.LEFT, padx=5)
        
    def _on_resize(self, event):
        """窗口大小变化处理"""
        if self.layout_manager and hasattr(self.layout_manager, 'apply_layout'):
            self.apply_layout()

class RadarSimulationController(Controller):
    """雷达仿真控制器"""
    
    def __init__(self, view: RadarSimulationView, model=None):
        super().__init__(view, model)
        self.view = view
        self.simulation_running = False
        self.setup_events()
        
    def setup_events(self):
        """设置事件处理"""
        # 获取雷达显示画布
        radar_canvas = self.view.get_widget('radar_display')
        if radar_canvas:
            # 绑定鼠标事件
            radar_canvas.bind("<Button-1>", self.on_canvas_click)
            radar_canvas.bind("<B1-Motion>", self.on_canvas_drag)
            radar_canvas.bind("<MouseWheel>", self.on_canvas_zoom)
            
    def on_canvas_click(self, event):
        """画布点击事件"""
        print(f"Canvas clicked at ({event.x}, {event.y})")
        
    def on_canvas_drag(self, event):
        """画布拖动事件"""
        print(f"Canvas dragged to ({event.x}, {event.y})")
        
    def on_canvas_zoom(self, event):
        """画布缩放事件"""
        delta = event.delta
        print(f"Canvas zoom: {delta}")
        
    def start_simulation(self):
        """开始仿真"""
        if not self.simulation_running:
            self.simulation_running = True
            self.view.status_label.config(text="仿真运行中...")
            # 这里可以启动仿真线程
            
    def stop_simulation(self):
        """停止仿真"""
        if self.simulation_running:
            self.simulation_running = False
            self.view.status_label.config(text="仿真已停止")
            
    def update_progress(self, value):
        """更新进度条"""
        self.view.progress_var.set(value)
        
    def update_status(self, message):
        """更新状态信息"""
        self.view.status_label.config(text=message)

# 主应用类
class AdvancedLayoutFramework:
    """高级布局框架演示应用"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("高级布局框架 - MVC模式实现")
        self.root.geometry("1200x800")
        
        # 设置样式
        self.setup_styles()
        
        # 创建菜单
        self.create_menu()
        
        # 创建主界面
        self.create_main_interface()
        
    def setup_styles(self):
        """设置应用样式"""
        style = ttk.Style()
        
        # 配置主题
        style.theme_use('clam')
        
        # 自定义样式
        style.configure('Title.TLabel',
                       font=('微软雅黑', 18, 'bold'),
                       foreground='#2C3E50')
        
        style.configure('Section.TLabelframe.Label',
                       font=('微软雅黑', 12, 'bold'),
                       foreground='#34495E')
        
        style.configure('Status.TLabel',
                       font=('Consolas', 9),
                       background='#ECF0F1',
                       foreground='#2C3E50',
                       padding=3)
        
    def create_menu(self):
        """创建菜单栏"""
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)
        
        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="文件", menu=file_menu)
        file_menu.add_command(label="新建", command=self.on_new)
        file_menu.add_command(label="打开", command=self.on_open)
        file_menu.add_separator()
        file_menu.add_command(label="退出", command=self.root.quit)
        
        # 视图菜单
        view_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="视图", menu=view_menu)
        
        # 布局模式子菜单
        layout_menu = tk.Menu(view_menu, tearoff=0)
        view_menu.add_cascade(label="布局模式", menu=layout_menu)
        layout_menu.add_radiobutton(label="自适应模式", command=self.set_adaptive_layout)
        layout_menu.add_radiobutton(label="固定模式", command=self.set_fixed_layout)
        layout_menu.add_radiobutton(label="紧凑模式", command=self.set_compact_layout)
        
        # 主题子菜单
        theme_menu = tk.Menu(view_menu, tearoff=0)
        view_menu.add_cascade(label="主题", menu=theme_menu)
        theme_menu.add_radiobutton(label="浅色主题", command=self.set_light_theme)
        theme_menu.add_radiobutton(label="深色主题", command=self.set_dark_theme)
        theme_menu.add_radiobutton(label="高对比度", command=self.set_high_contrast_theme)
        
        # 帮助菜单
        help_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="关于", command=self.on_about)
        
    def create_main_interface(self):
        """创建主界面"""
        # 标题栏
        title_frame = ttk.Frame(self.root)
        title_frame.pack(fill=tk.X, padx=10, pady=5)
        
        title_label = ttk.Label(title_frame, 
                               text="雷达电子对抗仿真系统 - MVC架构演示",
                               style='Title.TLabel')
        title_label.pack()
        
        # 创建视图和控制器
        self.view = RadarSimulationView(self.root)
        self.controller = RadarSimulationController(self.view)
        
        # 构建UI
        self.view.build_ui()
        self.view.frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 应用布局
        self.view.apply_layout()
        
        # 底部信息栏
        info_frame = ttk.Frame(self.root, relief=tk.SUNKEN, borderwidth=1)
        info_frame.pack(fill=tk.X, padx=10, pady=5)
        
        info_text = "当前布局: 响应式 | MVC架构: 视图-控制器分离 | 使用: tkinter/ttk 高级布局框架"
        info_label = ttk.Label(info_frame, text=info_text, style='Status.TLabel')
        info_label.pack(padx=5, pady=3)
        
    def on_new(self):
        """新建文件"""
        print("新建文件")
        
    def on_open(self):
        """打开文件"""
        print("打开文件")
        
    def on_about(self):
        """关于对话框"""
        about_text = """雷达电子对抗仿真系统 - MVC架构演示
        
版本: 1.0.0
作者: Python GUI 研究团队
描述: 展示tkinter/ttk在复杂布局和MVC架构中的高级应用"""
        
        tk.messagebox.showinfo("关于", about_text)
        
    def set_adaptive_layout(self):
        """设置自适应布局"""
        self.view.status_label.config(text="布局模式: 自适应")
        
    def set_fixed_layout(self):
        """设置固定布局"""
        self.view.status_label.config(text="布局模式: 固定")
        
    def set_compact_layout(self):
        """设置紧凑布局"""
        self.view.status_label.config(text="布局模式: 紧凑")
        
    def set_light_theme(self):
        """设置浅色主题"""
        self.view.status_label.config(text="主题: 浅色")
        
    def set_dark_theme(self):
        """设置深色主题"""
        self.view.status_label.config(text="主题: 深色")
        
    def set_high_contrast_theme(self):
        """设置高对比度主题"""
        self.view.status_label.config(text="主题: 高对比度")

# 主程序入口
if __name__ == "__main__":
    root = tk.Tk()
    
    # 设置窗口图标(如果有的话)
    try:
        root.iconbitmap("radar_icon.ico")
    except:
        pass
    
    app = AdvancedLayoutFramework(root)
    
    # 窗口居中
    root.update_idletasks()
    width = root.winfo_width()
    height = root.winfo_height()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = (screen_width - width) // 2
    y = (screen_height - height) // 2
    root.geometry(f'{width}x{height}+{x}+{y}')
    
    # 启动主循环
    root.mainloop()

4. 自定义控件的开发与应用

4.1 自定义控件架构设计

4.2 完整的自定义雷达显示控件实现

python 复制代码
"""
custom_radar_widget.py

自定义雷达显示控件实现
"""
import tkinter as tk
from tkinter import ttk
import math
import random
from typing import List, Tuple, Dict, Any
import colorsys
from dataclasses import dataclass
from enum import Enum

@dataclass
class RadarTarget:
    """雷达目标数据类"""
    x: float  # 归一化X坐标 (-1到1)
    y: float  # 归一化Y坐标 (-1到1)
    rcs: float  # 雷达截面积
    speed: float  # 速度
    track_id: int  # 航迹ID
    confidence: float  # 置信度

class DisplayMode(Enum):
    """显示模式枚举"""
    BASIC = "basic"  # 基本模式
    ADVANCED = "advanced"  # 高级模式
    TRACKING = "tracking"  # 跟踪模式
    ANALYSIS = "analysis"  # 分析模式

class CustomRadarWidget(ttk.Frame):
    """自定义雷达显示控件"""
    
    def __init__(self, parent, width=400, height=400, **kwargs):
        super().__init__(parent, **kwargs)
        self.width = width
        self.height = height
        self.display_mode = DisplayMode.ADVANCED
        
        # 雷达参数
        self.range_km = 100  # 探测距离(km)
        self.scan_line_angle = 0  # 扫描线角度(度)
        self.scan_speed = 1.0  # 扫描速度(度/帧)
        self.grid_visible = True
        self.axes_visible = True
        self.labels_visible = True
        
        # 目标数据
        self.targets: List[RadarTarget] = []
        self.track_history: Dict[int, List[Tuple[float, float]]] = {}
        
        # 颜色配置
        self.colors = {
            'background': '#1C2833',
            'grid': '#2C3E50',
            'axes': '#2ECC71',
            'scan_line': '#E74C3C',
            'target_low': '#2ECC71',
            'target_medium': '#F39C12',
            'target_high': '#E74C3C',
            'track': '#3498DB',
            'text': '#ECF0F1'
        }
        
        # 初始化UI
        self._init_ui()
        
    def _init_ui(self):
        """初始化UI"""
        # 创建主画布
        self.canvas = tk.Canvas(
            self,
            width=self.width,
            height=self.height,
            bg=self.colors['background'],
            highlightthickness=0
        )
        self.canvas.pack(fill=tk.BOTH, expand=True)
        
        # 创建控制面板
        self._create_control_panel()
        
        # 绑定事件
        self.canvas.bind('<Configure>', self._on_resize)
        self.canvas.bind('<Button-1>', self._on_canvas_click)
        self.canvas.bind('<B1-Motion>', self._on_canvas_drag)
        
        # 初始绘制
        self._draw_radar()
        
    def _create_control_panel(self):
        """创建控制面板"""
        control_frame = ttk.Frame(self)
        control_frame.pack(fill=tk.X, pady=5)
        
        # 显示模式选择
        ttk.Label(control_frame, text="显示模式:").pack(side=tk.LEFT, padx=5)
        
        mode_var = tk.StringVar(value=self.display_mode.value)
        mode_combo = ttk.Combobox(
            control_frame,
            textvariable=mode_var,
            values=[mode.value for mode in DisplayMode],
            state='readonly',
            width=12
        )
        mode_combo.pack(side=tk.LEFT, padx=5)
        mode_combo.bind('<<ComboboxSelected>>', 
                       lambda e: self.set_display_mode(DisplayMode(mode_var.get())))
        
        # 显示选项
        options_frame = ttk.Frame(control_frame)
        options_frame.pack(side=tk.LEFT, padx=20)
        
        self.grid_var = tk.BooleanVar(value=self.grid_visible)
        grid_cb = ttk.Checkbutton(options_frame, text="网格", 
                                 variable=self.grid_var,
                                 command=self._on_grid_toggle)
        grid_cb.pack(side=tk.LEFT, padx=5)
        
        self.axes_var = tk.BooleanVar(value=self.axes_visible)
        axes_cb = ttk.Checkbutton(options_frame, text="坐标轴", 
                                 variable=self.axes_var,
                                 command=self._on_axes_toggle)
        axes_cb.pack(side=tk.LEFT, padx=5)
        
        self.labels_var = tk.BooleanVar(value=self.labels_visible)
        labels_cb = ttk.Checkbutton(options_frame, text="标签", 
                                   variable=self.labels_var,
                                   command=self._on_labels_toggle)
        labels_cb.pack(side=tk.LEFT, padx=5)
        
        # 距离控制
        ttk.Label(control_frame, text="距离(km):").pack(side=tk.LEFT, padx=5)
        self.range_var = tk.IntVar(value=self.range_km)
        range_scale = ttk.Scale(
            control_frame,
            from_=10,
            to=500,
            variable=self.range_var,
            orient=tk.HORIZONTAL,
            length=150,
            command=self._on_range_change
        )
        range_scale.pack(side=tk.LEFT, padx=5)
        
    def set_display_mode(self, mode: DisplayMode):
        """设置显示模式"""
        self.display_mode = mode
        self._draw_radar()
        
    def _on_grid_toggle(self):
        """网格显示切换"""
        self.grid_visible = self.grid_var.get()
        self._draw_radar()
        
    def _on_axes_toggle(self):
        """坐标轴显示切换"""
        self.axes_visible = self.axes_var.get()
        self._draw_radar()
        
    def _on_labels_toggle(self):
        """标签显示切换"""
        self.labels_visible = self.labels_var.get()
        self._draw_radar()
        
    def _on_range_change(self, value):
        """距离变化"""
        self.range_km = int(float(value))
        self._draw_radar()
        
    def _on_resize(self, event):
        """画布大小变化"""
        if event.width > 10 and event.height > 10:
            self.width = event.width
            self.height = event.height
            self._draw_radar()
            
    def _on_canvas_click(self, event):
        """画布点击事件"""
        # 将点击坐标转换为雷达坐标
        radar_x, radar_y = self._screen_to_radar(event.x, event.y)
        print(f"点击位置: 屏幕({event.x}, {event.y}) -> 雷达({radar_x:.2f}, {radar_y:.2f})")
        
    def _on_canvas_drag(self, event):
        """画布拖动事件"""
        # 可以用于交互操作
        pass
        
    def _screen_to_radar(self, screen_x: int, screen_y: int) -> Tuple[float, float]:
        """屏幕坐标转雷达坐标"""
        center_x = self.width / 2
        center_y = self.height / 2
        radius = min(center_x, center_y) - 20
        
        dx = (screen_x - center_x) / radius
        dy = (screen_y - center_y) / radius
        
        return dx, dy
        
    def _radar_to_screen(self, radar_x: float, radar_y: float) -> Tuple[int, int]:
        """雷达坐标转屏幕坐标"""
        center_x = self.width / 2
        center_y = self.height / 2
        radius = min(center_x, center_y) - 20
        
        screen_x = center_x + radar_x * radius
        screen_y = center_y + radar_y * radius
        
        return int(screen_x), int(screen_y)
        
    def add_target(self, target: RadarTarget):
        """添加目标"""
        self.targets.append(target)
        
        # 更新航迹历史
        if target.track_id not in self.track_history:
            self.track_history[target.track_id] = []
        
        # 保留最近20个点
        self.track_history[target.track_id].append((target.x, target.y))
        if len(self.track_history[target.track_id]) > 20:
            self.track_history[target.track_id].pop(0)
            
        self._draw_radar()
        
    def clear_targets(self):
        """清除所有目标"""
        self.targets.clear()
        self.track_history.clear()
        self._draw_radar()
        
    def update_scan(self):
        """更新扫描线"""
        self.scan_line_angle = (self.scan_line_angle + self.scan_speed) % 360
        self._draw_radar()
        
    def _draw_radar(self):
        """绘制雷达图"""
        # 清除画布
        self.canvas.delete("all")
        
        if self.width < 10 or self.height < 10:
            return
            
        center_x = self.width / 2
        center_y = self.height / 2
        radius = min(center_x, center_y) - 20
        
        # 绘制网格
        if self.grid_visible:
            self._draw_grid(center_x, center_y, radius)
            
        # 绘制坐标轴
        if self.axes_visible:
            self._draw_axes(center_x, center_y, radius)
            
        # 绘制距离环和标签
        self._draw_range_rings(center_x, center_y, radius)
        
        # 绘制航迹历史
        if self.display_mode in [DisplayMode.TRACKING, DisplayMode.ANALYSIS]:
            self._draw_tracks(center_x, center_y, radius)
            
        # 绘制扫描线
        self._draw_scan_line(center_x, center_y, radius)
        
        # 绘制目标
        self._draw_targets(center_x, center_y, radius)
        
        # 绘制状态信息
        self._draw_status_info()
        
    def _draw_grid(self, center_x: float, center_y: float, radius: float):
        """绘制网格"""
        # 同心圆
        for i in range(1, 6):
            r = radius * i / 5
            self.canvas.create_oval(
                center_x - r, center_y - r,
                center_x + r, center_y + r,
                outline=self.colors['grid'],
                width=1,
                dash=(2, 2)
            )
            
        # 径向线
        for angle in range(0, 360, 30):
            rad = math.radians(angle)
            end_x = center_x + radius * math.sin(rad)
            end_y = center_y - radius * math.cos(rad)
            
            self.canvas.create_line(
                center_x, center_y, end_x, end_y,
                fill=self.colors['grid'],
                width=1,
                dash=(2, 2)
            )
            
    def _draw_axes(self, center_x: float, center_y: float, radius: float):
        """绘制坐标轴"""
        # X轴
        self.canvas.create_line(
            center_x - radius, center_y,
            center_x + radius, center_y,
            fill=self.colors['axes'],
            width=2
        )
        
        # Y轴
        self.canvas.create_line(
            center_x, center_y - radius,
            center_x, center_y + radius,
            fill=self.colors['axes'],
            width=2
        )
        
        # 方向标签
        if self.labels_visible:
            font = ("Arial", 10, "bold")
            
            # 北
            self.canvas.create_text(
                center_x, center_y - radius - 15,
                text="N", fill=self.colors['text'],
                font=font
            )
            
            # 东
            self.canvas.create_text(
                center_x + radius + 15, center_y,
                text="E", fill=self.colors['text'],
                font=font
            )
            
            # 南
            self.canvas.create_text(
                center_x, center_y + radius + 15,
                text="S", fill=self.colors['text'],
                font=font
            )
            
            # 西
            self.canvas.create_text(
                center_x - radius - 15, center_y,
                text="W", fill=self.colors['text'],
                font=font
            )
            
    def _draw_range_rings(self, center_x: float, center_y: float, radius: float):
        """绘制距离环和标签"""
        for i in range(1, 6):
            r = radius * i / 5
            distance_km = self.range_km * i / 5
            
            # 绘制距离环
            self.canvas.create_oval(
                center_x - r, center_y - r,
                center_x + r, center_y + r,
                outline=self.colors['grid'],
                width=1
            )
            
            # 绘制距离标签
            if self.labels_visible:
                self.canvas.create_text(
                    center_x + 5, center_y - r + 5,
                    text=f"{distance_km}km",
                    fill=self.colors['text'],
                    font=("Arial", 8),
                    anchor=tk.W
                )
                
    def _draw_scan_line(self, center_x: float, center_y: float, radius: float):
        """绘制扫描线"""
        rad = math.radians(self.scan_line_angle)
        end_x = center_x + radius * math.sin(rad)
        end_y = center_y - radius * math.cos(rad)
        
        self.canvas.create_line(
            center_x, center_y, end_x, end_y,
            fill=self.colors['scan_line'],
            width=2,
            arrow=tk.LAST
        )
        
    def _draw_targets(self, center_x: float, center_y: float, radius: float):
        """绘制目标"""
        for target in self.targets:
            # 计算屏幕坐标
            screen_x, screen_y = self._radar_to_screen(target.x, target.y)
            
            # 根据RCS确定目标大小和颜色
            if target.rcs < 2:
                color = self.colors['target_low']
                size = 4
            elif target.rcs < 5:
                color = self.colors['target_medium']
                size = 6
            else:
                color = self.colors['target_high']
                size = 8
                
            # 绘制目标
            self.canvas.create_oval(
                screen_x - size, screen_y - size,
                screen_x + size, screen_y + size,
                fill=color,
                outline='white',
                width=1
            )
            
            # 绘制目标ID
            if self.labels_visible:
                self.canvas.create_text(
                    screen_x, screen_y - size - 10,
                    text=f"T{target.track_id}",
                    fill=self.colors['text'],
                    font=("Arial", 8, "bold")
                )
                
    def _draw_tracks(self, center_x: float, center_y: float, radius: float):
        """绘制航迹"""
        for track_id, points in self.track_history.items():
            if len(points) < 2:
                continue
                
            # 绘制航迹线
            screen_points = []
            for radar_x, radar_y in points:
                screen_x, screen_y = self._radar_to_screen(radar_x, radar_y)
                screen_points.extend([screen_x, screen_y])
                
            self.canvas.create_line(
                *screen_points,
                fill=self.colors['track'],
                width=1,
                smooth=True
            )
            
    def _draw_status_info(self):
        """绘制状态信息"""
        info_text = [
            f"模式: {self.display_mode.value}",
            f"距离: {self.range_km} km",
            f"目标数: {len(self.targets)}",
            f"扫描角: {self.scan_line_angle:.1f}°"
        ]
        
        y_pos = 10
        for text in info_text:
            self.canvas.create_text(
                10, y_pos,
                text=text,
                fill=self.colors['text'],
                font=("Consolas", 9),
                anchor=tk.W
            )
            y_pos += 20

# 测试代码
def test_custom_radar_widget():
    """测试自定义雷达控件"""
    root = tk.Tk()
    root.title("自定义雷达控件测试")
    root.geometry("800x600")
    
    # 创建雷达控件
    radar = CustomRadarWidget(root, width=600, height=400)
    radar.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
    
    # 添加测试目标
    def add_test_targets():
        radar.clear_targets()
        
        # 添加几个测试目标
        targets = [
            RadarTarget(0.3, 0.4, 1.5, 200, 1, 0.9),
            RadarTarget(-0.2, 0.6, 3.0, 150, 2, 0.8),
            RadarTarget(0.5, -0.3, 6.0, 300, 3, 0.95),
            RadarTarget(-0.4, -0.5, 2.0, 100, 4, 0.7)
        ]
        
        for target in targets:
            radar.add_target(target)
    
    # 控制面板
    control_frame = ttk.Frame(root)
    control_frame.pack(fill=tk.X, padx=10, pady=5)
    
    ttk.Button(control_frame, text="添加目标", 
              command=add_test_targets).pack(side=tk.LEFT, padx=5)
    
    ttk.Button(control_frame, text="清除目标", 
              command=radar.clear_targets).pack(side=tk.LEFT, padx=5)
    
    ttk.Button(control_frame, text="更新扫描", 
              command=radar.update_scan).pack(side=tk.LEFT, padx=5)
    
    # 启动动画
    def animate():
        radar.update_scan()
        root.after(50, animate)  # 20 FPS
    
    animate()
    
    root.mainloop()

if __name__ == "__main__":
    test_custom_radar_widget()

5. 主题引擎与皮肤系统实现

python 复制代码
"""
theme_engine.py

现代化主题引擎实现
"""
import tkinter as tk
from tkinter import ttk
import json
from pathlib import Path
from typing import Dict, Any, Optional
from dataclasses import dataclass, asdict
from enum import Enum
import colorsys

@dataclass
class ColorScheme:
    """颜色方案"""
    primary: str
    secondary: str
    success: str
    warning: str
    danger: str
    info: str
    background: str
    foreground: str
    surface: str
    border: str
    text_primary: str
    text_secondary: str
    text_disabled: str

@dataclass
class ThemeConfig:
    """主题配置"""
    name: str
    description: str
    colors: ColorScheme
    fonts: Dict[str, Any]
    spacing: Dict[str, int]
    border_radius: Dict[str, int]
    shadows: Dict[str, str]

class Theme(Enum):
    """主题枚举"""
    LIGHT = "light"
    DARK = "dark"
    HIGH_CONTRAST = "high_contrast"
    BLUE_DARK = "blue_dark"
    GREEN_LIGHT = "green_light"

class ThemeEngine:
    """主题引擎"""
    
    def __init__(self):
        self.current_theme: Optional[Theme] = None
        self.themes: Dict[Theme, ThemeConfig] = {}
        self.widget_registry = {}  # 注册的控件
        self._load_builtin_themes()
        
    def _load_builtin_themes(self):
        """加载内置主题"""
        # 浅色主题
        self.themes[Theme.LIGHT] = ThemeConfig(
            name="浅色主题",
            description="适合日间使用的明亮主题",
            colors=ColorScheme(
                primary="#3498DB",
                secondary="#2ECC71",
                success="#27AE60",
                warning="#F39C12",
                danger="#E74C3C",
                info="#17A2B8",
                background="#F8F9FA",
                foreground="#ECF0F1",
                surface="#FFFFFF",
                border="#DEE2E6",
                text_primary="#212529",
                text_secondary="#6C757D",
                text_disabled="#ADB5BD"
            ),
            fonts={
                "family": "微软雅黑, Segoe UI, Arial",
                "size_small": 10,
                "size_normal": 12,
                "size_large": 14,
                "size_title": 18,
                "weight_normal": "normal",
                "weight_bold": "bold"
            },
            spacing={
                "xs": 4,
                "sm": 8,
                "md": 12,
                "lg": 16,
                "xl": 24
            },
            border_radius={
                "sm": 4,
                "md": 8,
                "lg": 12,
                "xl": 16
            },
            shadows={
                "sm": "0 1px 3px rgba(0,0,0,0.12)",
                "md": "0 4px 6px rgba(0,0,0,0.1)",
                "lg": "0 10px 15px rgba(0,0,0,0.1)"
            }
        )
        
        # 深色主题
        self.themes[Theme.DARK] = ThemeConfig(
            name="深色主题",
            description="适合夜间使用的深色主题",
            colors=ColorScheme(
                primary="#3498DB",
                secondary="#2ECC71",
                success="#27AE60",
                warning="#F39C12",
                danger="#E74C3C",
                info="#17A2B8",
                background="#1C2833",
                foreground="#2C3E50",
                surface="#34495E",
                border="#566573",
                text_primary="#ECF0F1",
                text_secondary="#BDC3C7",
                text_disabled="#7F8C8D"
            ),
            fonts={
                "family": "微软雅黑, Segoe UI, Arial",
                "size_small": 10,
                "size_normal": 12,
                "size_large": 14,
                "size_title": 18,
                "weight_normal": "normal",
                "weight_bold": "bold"
            },
            spacing={
                "xs": 4,
                "sm": 8,
                "md": 12,
                "lg": 16,
                "xl": 24
            },
            border_radius={
                "sm": 4,
                "md": 8,
                "lg": 12,
                "xl": 16
            },
            shadows={
                "sm": "0 1px 3px rgba(0,0,0,0.3)",
                "md": "0 4px 6px rgba(0,0,0,0.25)",
                "lg": "0 10px 15px rgba(0,0,0,0.2)"
            }
        )
        
        # 高对比度主题
        self.themes[Theme.HIGH_CONTRAST] = ThemeConfig(
            name="高对比度主题",
            description="高可访问性高对比度主题",
            colors=ColorScheme(
                primary="#0000FF",
                secondary="#008000",
                success="#006400",
                warning="#FFA500",
                danger="#FF0000",
                info="#008080",
                background="#000000",
                foreground="#FFFFFF",
                surface="#2A2A2A",
                border="#FFFFFF",
                text_primary="#FFFFFF",
                text_secondary="#CCCCCC",
                text_disabled="#666666"
            ),
            fonts={
                "family": "Arial, sans-serif",
                "size_small": 12,
                "size_normal": 14,
                "size_large": 16,
                "size_title": 20,
                "weight_normal": "bold",
                "weight_bold": "bold"
            },
            spacing={
                "xs": 6,
                "sm": 10,
                "md": 14,
                "lg": 18,
                "xl": 28
            },
            border_radius={
                "sm": 0,
                "md": 0,
                "lg": 0,
                "xl": 0
            },
            shadows={
                "sm": "none",
                "md": "none",
                "lg": "none"
            }
        )
        
    def register_widget(self, widget, widget_type: str):
        """注册控件"""
        widget_id = id(widget)
        self.widget_registry[widget_id] = {
            'widget': widget,
            'type': widget_type
        }
        
    def apply_theme(self, theme: Theme):
        """应用主题"""
        if theme not in self.themes:
            raise ValueError(f"主题 '{theme}' 不存在")
            
        self.current_theme = theme
        theme_config = self.themes[theme]
        
        # 创建样式对象
        style = ttk.Style()
        
        # 设置字体
        font_family = theme_config.fonts['family']
        font_sizes = {
            'small': theme_config.fonts['size_small'],
            'normal': theme_config.fonts['size_normal'],
            'large': theme_config.fonts['size_large'],
            'title': theme_config.fonts['size_title']
        }
        
        # 配置tkinter默认颜色
        root = tk._default_root
        if root:
            root.configure(bg=theme_config.colors.background)
            
        # 配置ttk样式
        self._configure_ttk_styles(style, theme_config, font_family, font_sizes)
        
        # 更新已注册的控件
        self._update_registered_widgets(theme_config)
        
        return theme_config
        
    def _configure_ttk_styles(self, style, theme_config, font_family, font_sizes):
        """配置ttk样式"""
        colors = theme_config.colors
        
        # 基础样式
        style.configure('.',
            background=colors.background,
            foreground=colors.text_primary,
            fieldbackground=colors.surface,
            troughcolor=colors.foreground,
            selectbackground=colors.primary,
            selectforeground=colors.text_primary,
            borderwidth=1,
            focusthickness=3,
            focuscolor=''
        )
        
        # 按钮样式
        self._configure_button_styles(style, colors, font_family, font_sizes)
        
        # 标签样式
        self._configure_label_styles(style, colors, font_family, font_sizes)
        
        # 输入框样式
        self._configure_entry_styles(style, colors)
        
        # 组合框样式
        self._configure_combobox_styles(style, colors)
        
        # 进度条样式
        self._configure_progressbar_styles(style, colors)
        
        # Notebook样式
        self._configure_notebook_styles(style, colors)
        
        # Treeview样式
        self._configure_treeview_styles(style, colors)
        
    def _configure_button_styles(self, style, colors, font_family, font_sizes):
        """配置按钮样式"""
        # 默认按钮
        style.configure('TButton',
            padding=(12, 6),
            font=(font_family, font_sizes['normal']),
            background=colors.primary,
            foreground=colors.text_primary,
            borderwidth=0,
            focusthickness=3,
            focuscolor=colors.primary
        )
        
        style.map('TButton',
            background=[('active', self._adjust_color(colors.primary, -20))],
            foreground=[('active', colors.text_primary)]
        )
        
        # 主按钮
        style.configure('Primary.TButton',
            background=colors.primary,
            foreground='white'
        )
        
        # 成功按钮
        style.configure('Success.TButton',
            background=colors.success,
            foreground='white'
        )
        
        # 警告按钮
        style.configure('Warning.TButton',
            background=colors.warning,
            foreground='white'
        )
        
        # 危险按钮
        style.configure('Danger.TButton',
            background=colors.danger,
            foreground='white'
        )
        
    def _configure_label_styles(self, style, colors, font_family, font_sizes):
        """配置标签样式"""
        # 默认标签
        style.configure('TLabel',
            font=(font_family, font_sizes['normal']),
            background=colors.background,
            foreground=colors.text_primary
        )
        
        # 标题标签
        style.configure('Title.TLabel',
            font=(font_family, font_sizes['title'], 'bold'),
            foreground=colors.text_primary
        )
        
        # 副标题标签
        style.configure('Subtitle.TLabel',
            font=(font_family, font_sizes['large']),
            foreground=colors.text_secondary
        )
        
        # 小号标签
        style.configure('Small.TLabel',
            font=(font_family, font_sizes['small']),
            foreground=colors.text_secondary
        )
        
    def _configure_entry_styles(self, style, colors):
        """配置输入框样式"""
        style.configure('TEntry',
            fieldbackground=colors.surface,
            foreground=colors.text_primary,
            borderwidth=1,
            relief='flat',
            padding=8
        )
        
        style.map('TEntry',
            fieldbackground=[('readonly', colors.foreground)],
            foreground=[('readonly', colors.text_secondary)]
        )
        
    def _configure_combobox_styles(self, style, colors):
        """配置组合框样式"""
        style.configure('TCombobox',
            fieldbackground=colors.surface,
            foreground=colors.text_primary,
            borderwidth=1,
            relief='flat',
            padding=8
        )
        
        style.map('TCombobox',
            fieldbackground=[
                ('readonly', colors.surface),
                ('disabled', colors.foreground)
            ],
            foreground=[
                ('readonly', colors.text_primary),
                ('disabled', colors.text_disabled)
            ]
        )
        
    def _configure_progressbar_styles(self, style, colors):
        """配置进度条样式"""
        style.configure('Horizontal.TProgressbar',
            background=colors.primary,
            troughcolor=colors.foreground,
            borderwidth=0,
            lightcolor=colors.primary,
            darkcolor=colors.primary
        )
        
    def _configure_notebook_styles(self, style, colors):
        """配置Notebook样式"""
        style.configure('TNotebook',
            background=colors.background,
            borderwidth=0
        )
        
        style.configure('TNotebook.Tab',
            padding=(20, 8),
            background=colors.foreground,
            foreground=colors.text_secondary,
            borderwidth=0
        )
        
        style.map('TNotebook.Tab',
            background=[
                ('selected', colors.background),
                ('active', colors.primary)
            ],
            foreground=[
                ('selected', colors.text_primary),
                ('active', 'white')
            ]
        )
        
    def _configure_treeview_styles(self, style, colors):
        """配置Treeview样式"""
        style.configure('Treeview',
            background=colors.surface,
            foreground=colors.text_primary,
            fieldbackground=colors.surface,
            borderwidth=0
        )
        
        style.map('Treeview',
            background=[('selected', colors.primary)],
            foreground=[('selected', 'white')]
        )
        
        style.configure('Treeview.Heading',
            background=colors.foreground,
            foreground=colors.text_primary,
            borderwidth=0,
            relief='flat'
        )
        
    def _update_registered_widgets(self, theme_config):
        """更新已注册的控件"""
        colors = theme_config.colors
        
        for widget_info in self.widget_registry.values():
            widget = widget_info['widget']
            widget_type = widget_info['type']
            
            try:
                if widget_type == 'tk':
                    # 直接更新tkinter控件
                    if isinstance(widget, (tk.Frame, tk.LabelFrame)):
                        widget.configure(bg=colors.background)
                    elif isinstance(widget, tk.Label):
                        widget.configure(bg=colors.background, fg=colors.text_primary)
                    elif isinstance(widget, tk.Button):
                        widget.configure(bg=colors.primary, fg='white',
                                        activebackground=self._adjust_color(colors.primary, -20),
                                        activeforeground='white')
                    elif isinstance(widget, tk.Entry):
                        widget.configure(bg=colors.surface, fg=colors.text_primary,
                                        insertbackground=colors.text_primary)
                    elif isinstance(widget, tk.Text):
                        widget.configure(bg=colors.surface, fg=colors.text_primary,
                                        insertbackground=colors.text_primary)
                    elif isinstance(widget, tk.Canvas):
                        widget.configure(bg=colors.background)
                elif widget_type == 'custom':
                    # 自定义控件的更新方法
                    if hasattr(widget, 'update_theme'):
                        widget.update_theme(theme_config)
            except Exception as e:
                print(f"更新控件时出错: {e}")
                
    def _adjust_color(self, hex_color: str, amount: int) -> str:
        """调整颜色亮度"""
        # 移除#号
        hex_color = hex_color.lstrip('#')
        
        # 转换为RGB
        r = int(hex_color[0:2], 16)
        g = int(hex_color[2:4], 16)
        b = int(hex_color[4:6], 16)
        
        # 调整亮度
        r = max(0, min(255, r + amount))
        g = max(0, min(255, g + amount))
        b = max(0, min(255, b + amount))
        
        # 转回十六进制
        return f"#{r:02x}{g:02x}{b:02x}"
        
    def save_theme(self, theme: Theme, filepath: str):
        """保存主题到文件"""
        if theme not in self.themes:
            raise ValueError(f"主题 '{theme}' 不存在")
            
        theme_config = self.themes[theme]
        
        # 转换为可序列化的字典
        data = {
            'name': theme_config.name,
            'description': theme_config.description,
            'colors': asdict(theme_config.colors),
            'fonts': theme_config.fonts,
            'spacing': theme_config.spacing,
            'border_radius': theme_config.border_radius,
            'shadows': theme_config.shadows
        }
        
        with open(filepath, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
            
    def load_theme(self, filepath: str, theme_name: str) -> Theme:
        """从文件加载主题"""
        with open(filepath, 'r', encoding='utf-8') as f:
            data = json.load(f)
            
        # 创建主题配置
        theme_config = ThemeConfig(
            name=data['name'],
            description=data['description'],
            colors=ColorScheme(**data['colors']),
            fonts=data['fonts'],
            spacing=data['spacing'],
            border_radius=data['border_radius'],
            shadows=data['shadows']
        )
        
        # 创建新主题
        theme = Theme(theme_name)
        self.themes[theme] = theme_config
        
        return theme

# 主题切换演示应用
class ThemeDemoApp:
    """主题演示应用"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("主题引擎演示")
        self.root.geometry("1000x700")
        
        # 创建主题引擎
        self.theme_engine = ThemeEngine()
        
        # 设置初始主题
        self.current_theme = Theme.LIGHT
        
        # 构建UI
        self._build_ui()
        
        # 应用初始主题
        self._apply_theme(self.current_theme)
        
    def _build_ui(self):
        """构建UI"""
        # 主容器
        main_container = ttk.Frame(self.root)
        main_container.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # 标题
        title_label = ttk.Label(main_container, 
                               text="主题引擎演示系统",
                               style='Title.TLabel')
        title_label.pack(pady=(0, 20))
        
        # 主题选择区域
        self._build_theme_selection(main_container)
        
        # 控件演示区域
        self._build_widget_demo(main_container)
        
        # 注册控件到主题引擎
        self._register_widgets()
        
    def _build_theme_selection(self, parent):
        """构建主题选择区域"""
        theme_frame = ttk.LabelFrame(parent, text="主题选择", padding=20)
        theme_frame.pack(fill=tk.X, pady=(0, 20))
        
        # 主题按钮
        themes_frame = ttk.Frame(theme_frame)
        themes_frame.pack()
        
        themes = [
            ("浅色主题", Theme.LIGHT, "#F8F9FA"),
            ("深色主题", Theme.DARK, "#1C2833"),
            ("高对比度", Theme.HIGH_CONTRAST, "#000000"),
            ("蓝色深色", Theme.BLUE_DARK, "#1C2833"),
            ("绿色浅色", Theme.GREEN_LIGHT, "#F8F9FA")
        ]
        
        for i, (text, theme, color) in enumerate(themes):
            btn = ttk.Button(
                themes_frame,
                text=text,
                command=lambda t=theme: self._apply_theme(t)
            )
            btn.grid(row=0, column=i, padx=5)
            
            # 显示主题颜色预览
            preview = tk.Frame(themes_frame, bg=color, width=20, height=20)
            preview.grid(row=1, column=i, pady=5)
            
        # 当前主题显示
        self.current_theme_label = ttk.Label(theme_frame, 
                                           text=f"当前主题: {self.current_theme.value}",
                                           style='Subtitle.TLabel')
        self.current_theme_label.pack(pady=(10, 0))
        
    def _build_widget_demo(self, parent):
        """构建控件演示区域"""
        # 使用Notebook组织不同类型的控件
        notebook = ttk.Notebook(parent)
        notebook.pack(fill=tk.BOTH, expand=True)
        
        # 基本控件标签页
        basic_tab = ttk.Frame(notebook)
        self._build_basic_widgets(basic_tab)
        notebook.add(basic_tab, text="基本控件")
        
        # 输入控件标签页
        input_tab = ttk.Frame(notebook)
        self._build_input_widgets(input_tab)
        notebook.add(input_tab, text="输入控件")
        
        # 复杂控件标签页
        complex_tab = ttk.Frame(notebook)
        self._build_complex_widgets(complex_tab)
        notebook.add(complex_tab, text="复杂控件")
        
    def _build_basic_widgets(self, parent):
        """构建基本控件演示"""
        # 使用网格布局
        row = 0
        
        # 标签
        ttk.Label(parent, text="不同样式的标签:").grid(
            row=row, column=0, sticky=tk.W, padx=10, pady=10
        )
        row += 1
        
        ttk.Label(parent, text="普通标签").grid(
            row=row, column=0, sticky=tk.W, padx=20, pady=5
        )
        
        ttk.Label(parent, text="标题标签", style='Title.TLabel').grid(
            row=row, column=1, sticky=tk.W, padx=20, pady=5
        )
        
        ttk.Label(parent, text="副标题标签", style='Subtitle.TLabel').grid(
            row=row, column=2, sticky=tk.W, padx=20, pady=5
        )
        
        ttk.Label(parent, text="小号标签", style='Small.TLabel').grid(
            row=row, column=3, sticky=tk.W, padx=20, pady=5
        )
        row += 1
        
        # 分隔线
        ttk.Separator(parent, orient=tk.HORIZONTAL).grid(
            row=row, column=0, columnspan=4, sticky=tk.EW, padx=10, pady=20
        )
        row += 1
        
        # 按钮
        ttk.Label(parent, text="不同样式的按钮:").grid(
            row=row, column=0, sticky=tk.W, padx=10, pady=10
        )
        row += 1
        
        ttk.Button(parent, text="默认按钮").grid(
            row=row, column=0, padx=20, pady=5
        )
        
        ttk.Button(parent, text="主按钮", style='Primary.TButton').grid(
            row=row, column=1, padx=20, pady=5
        )
        
        ttk.Button(parent, text="成功按钮", style='Success.TButton').grid(
            row=row, column=2, padx=20, pady=5
        )
        
        ttk.Button(parent, text="警告按钮", style='Warning.TButton').grid(
            row=row, column=3, padx=20, pady=5
        )
        
        ttk.Button(parent, text="危险按钮", style='Danger.TButton').grid(
            row=row, column=4, padx=20, pady=5
        )
        row += 1
        
        # 配置列权重
        for i in range(5):
            parent.grid_columnconfigure(i, weight=1)
            
    def _build_input_widgets(self, parent):
        """构建输入控件演示"""
        row = 0
        
        # 输入框
        ttk.Label(parent, text="输入框:").grid(
            row=row, column=0, sticky=tk.W, padx=10, pady=10
        )
        row += 1
        
        ttk.Entry(parent, width=20).grid(
            row=row, column=0, padx=20, pady=5, sticky=tk.W
        )
        
        ttk.Entry(parent, width=20, state='readonly').grid(
            row=row, column=1, padx=20, pady=5, sticky=tk.W
        )
        
        ttk.Entry(parent, width=20, state='disabled').grid(
            row=row, column=2, padx=20, pady=5, sticky=tk.W
        )
        row += 1
        
        # 组合框
        ttk.Label(parent, text="组合框:").grid(
            row=row, column=0, sticky=tk.W, padx=10, pady=10
        )
        row += 1
        
        values = ["选项1", "选项2", "选项3", "选项4"]
        
        combo1 = ttk.Combobox(parent, values=values, width=18)
        combo1.grid(row=row, column=0, padx=20, pady=5, sticky=tk.W)
        combo1.set("选项1")
        
        combo2 = ttk.Combobox(parent, values=values, width=18, state='readonly')
        combo2.grid(row=row, column=1, padx=20, pady=5, sticky=tk.W)
        combo2.set("选项2")
        
        combo3 = ttk.Combobox(parent, values=values, width=18, state='disabled')
        combo3.grid(row=row, column=2, padx=20, pady=5, sticky=tk.W)
        row += 1
        
        # 复选框
        ttk.Label(parent, text="复选框:").grid(
            row=row, column=0, sticky=tk.W, padx=10, pady=10
        )
        row += 1
        
        vars = []
        for i in range(4):
            var = tk.BooleanVar(value=(i % 2 == 0))
            cb = ttk.Checkbutton(parent, text=f"选项 {i+1}", variable=var)
            cb.grid(row=row, column=i, padx=20, pady=5, sticky=tk.W)
            vars.append(var)
        row += 1
        
        # 单选按钮
        ttk.Label(parent, text="单选按钮:").grid(
            row=row, column=0, sticky=tk.W, padx=10, pady=10
        )
        row += 1
        
        radio_var = tk.StringVar(value="选项1")
        for i in range(4):
            rb = ttk.Radiobutton(parent, text=f"选项 {i+1}", 
                                variable=radio_var, value=f"选项{i+1}")
            rb.grid(row=row, column=i, padx=20, pady=5, sticky=tk.W)
        row += 1
        
        # 滑块
        ttk.Label(parent, text="滑块:").grid(
            row=row, column=0, sticky=tk.W, padx=10, pady=10
        )
        row += 1
        
        scale_var = tk.DoubleVar(value=50)
        ttk.Scale(parent, from_=0, to=100, variable=scale_var, 
                 orient=tk.HORIZONTAL, length=300).grid(
            row=row, column=0, columnspan=4, padx=20, pady=5, sticky=tk.W
        )
        
    def _build_complex_widgets(self, parent):
        """构建复杂控件演示"""
        # 使用PanedWindow
        paned = ttk.PanedWindow(parent, orient=tk.HORIZONTAL)
        paned.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 左侧:Treeview
        left_frame = ttk.Frame(paned)
        ttk.Label(left_frame, text="Treeview示例", style='Subtitle.TLabel').pack(pady=10)
        
        # 创建Treeview
        columns = ("名称", "类型", "大小", "修改时间")
        tree = ttk.Treeview(left_frame, columns=columns, show="headings", height=10)
        
        # 设置列标题
        for col in columns:
            tree.heading(col, text=col)
            tree.column(col, width=100)
            
        # 添加示例数据
        sample_data = [
            ("文档.txt", "文本文件", "1.2KB", "2024-01-10"),
            ("图片.jpg", "图像文件", "2.5MB", "2024-01-09"),
            ("报告.pdf", "PDF文件", "3.1MB", "2024-01-08"),
            ("数据.csv", "数据文件", "450KB", "2024-01-07"),
            ("程序.py", "Python文件", "15KB", "2024-01-06")
        ]
        
        for item in sample_data:
            tree.insert("", tk.END, values=item)
            
        # 添加滚动条
        tree_scroll = ttk.Scrollbar(left_frame, orient=tk.VERTICAL, command=tree.yview)
        tree.configure(yscrollcommand=tree_scroll.set)
        
        tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        tree_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        
        paned.add(left_frame, weight=1)
        
        # 右侧:进度条和更多控件
        right_frame = ttk.Frame(paned)
        
        # 进度条
        ttk.Label(right_frame, text="进度条示例", style='Subtitle.TLabel').pack(pady=10)
        
        progress_var = tk.DoubleVar(value=30)
        progress = ttk.Progressbar(right_frame, variable=progress_var, 
                                  maximum=100, length=200)
        progress.pack(pady=10)
        
        ttk.Label(right_frame, text=f"进度: {progress_var.get()}%").pack()
        
        # 控制进度条的按钮
        def increase_progress():
            current = progress_var.get()
            if current < 100:
                progress_var.set(current + 10)
                
        def decrease_progress():
            current = progress_var.get()
            if current > 0:
                progress_var.set(current - 10)
                
        btn_frame = ttk.Frame(right_frame)
        btn_frame.pack(pady=20)
        
        ttk.Button(btn_frame, text="增加", command=increase_progress).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="减少", command=decrease_progress).pack(side=tk.LEFT, padx=5)
        
        paned.add(right_frame, weight=1)
        
    def _register_widgets(self):
        """注册控件到主题引擎"""
        # 遍历所有控件并注册
        def register_recursive(widget):
            # 获取widget的所有子控件
            children = widget.winfo_children()
            for child in children:
                # 注册控件
                if isinstance(child, (tk.Widget, ttk.Widget)):
                    widget_type = 'tk' if isinstance(child, tk.Widget) else 'ttk'
                    self.theme_engine.register_widget(child, widget_type)
                    
                # 递归注册子控件的子控件
                register_recursive(child)
                
        # 从根窗口开始注册
        register_recursive(self.root)
        
    def _apply_theme(self, theme: Theme):
        """应用主题"""
        self.current_theme = theme
        
        # 通过主题引擎应用主题
        theme_config = self.theme_engine.apply_theme(theme)
        
        # 更新当前主题标签
        self.current_theme_label.config(
            text=f"当前主题: {theme_config.name}"
        )

# 主程序入口
if __name__ == "__main__":
    root = tk.Tk()
    app = ThemeDemoApp(root)
    
    # 窗口居中
    root.update_idletasks()
    width = root.winfo_width()
    height = root.winfo_height()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = (screen_width - width) // 2
    y = (screen_height - height) // 2
    root.geometry(f'{width}x{height}+{x}+{y}')
    
    root.mainloop()

总结与展望

已实现的核心功能总结

  1. 高级布局系统

    • 实现了响应式布局管理器

    • 支持多种布局模式混合使用

    • 提供了MVC架构的布局框架

  2. 自定义控件开发

    • 创建了专业的雷达显示控件

    • 实现了可扩展的控件架构

    • 支持多种显示模式和交互功能

  3. 主题引擎系统

    • 完整的主题管理引擎

    • 支持动态主题切换

    • 提供了丰富的内置主题

    • 支持主题的保存和加载

技术亮点

性能优化建议

  1. 渲染优化

    • 使用双缓冲技术减少闪烁

    • 增量更新而不是全量重绘

    • Canvas对象的缓存重用

  2. 内存管理

    • 及时释放不再使用的控件

    • 使用弱引用管理对象关系

    • 大数据集的虚拟化显示

  3. 响应性优化

    • 长时间操作放在后台线程

    • 使用事件队列避免阻塞

    • 增量数据加载和显示

扩展方向

  1. 更多专业控件

    • 频谱分析仪控件

    • 信号波形显示器

    • 三维雷达显示器

    • 电子战态势图

  2. 高级功能

    • 插件系统支持

    • 脚本自动化接口

    • 数据导入导出

    • 远程控制接口

  3. 部署优化

    • 单文件打包

    • 跨平台适配

    • 安装程序制作

    • 自动更新机制

相关推荐
城数派4 小时前
2025年全国地级市间驾车出行距离和出行时间矩阵数据
数据库·arcgis·信息可视化·数据分析
wgzrmlrm744 小时前
SQL实现按用户偏好进行分组汇总_自定义聚合规则
jvm·数据库·python
7年前端辞职转AI4 小时前
Python 变量
python·编程语言
7年前端辞职转AI4 小时前
Python 数据类型
python·编程语言
冰块的旅行4 小时前
python环境导出
python
曲幽5 小时前
我用fastapi-scaff搭了个项目,两天工期缩到两小时,老板以为我开挂了
python·api·fastapi·web·celery·cli·db·alembic·fastapi-scaff
半点闲5 小时前
入门 SQLAlchemy 教程:从 0 到 1 创建数据库
数据库·python·sqlite·sqlalchemy
好家伙VCC5 小时前
# 发散创新:基于事件驱动架构的实时日志监控系统设计与实现在现代分布式系统中,**事件驱动编程模型**正
java·python·架构
测试19985 小时前
postman接口测试详解
自动化测试·软件测试·python·测试工具·测试用例·接口测试·postman