"""图表框架相关逻辑(Step 3 重构)。 从 pqAutomationApp.PQAutomationApp 中搬迁而来。每个函数第一行 `self = app` 以保留原有 `self.xxx` 属性访问不变。 """ import tkinter as tk import ttkbootstrap as ttk import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from app.views.pq_debug_panel import PQDebugPanel def init_gamut_chart(self): """初始化色域图表 - 手动设置subplot位置,完全避免重叠""" container = ttk.Frame(self.gamut_chart_frame) container.pack(expand=True, fill=tk.BOTH) self.gamut_fig = plt.Figure(figsize=(14, 6), dpi=100) self.gamut_canvas = FigureCanvasTkAgg(self.gamut_fig, master=container) canvas_widget = self.gamut_canvas.get_tk_widget() canvas_widget.pack(expand=True, fill=tk.BOTH) # ✅ 恢复原来的大尺寸:0.84 高度 self.gamut_ax_xy = self.gamut_fig.add_axes( [0.02, 0.08, 0.46, 0.84] ) # ← 改回 0.84 self.gamut_ax_uv = self.gamut_fig.add_axes( [0.52, 0.08, 0.46, 0.84] ) # ← 改回 0.84 # 初始化XY图 self.gamut_ax_xy.set_xlim(0, 600) self.gamut_ax_xy.set_ylim(600, 0) self.gamut_ax_xy.axis("off") self.gamut_ax_xy.set_clip_on(False) # 初始化UV图 self.gamut_ax_uv.set_xlim(0, 600) self.gamut_ax_uv.set_ylim(600, 0) self.gamut_ax_uv.axis("off") self.gamut_ax_uv.set_clip_on(False) # 调整标题位置:y=0.98 self.gamut_fig.suptitle("色域测试", fontsize=12, y=0.98) self.gamut_canvas.draw() def init_gamma_chart(self): """初始化Gamma曲线图表 - 左侧曲线 + 右侧表格(✅ 4列 + 通用说明)""" container = ttk.Frame(self.gamma_chart_frame) container.pack(expand=True, fill=tk.BOTH) self.gamma_fig = plt.Figure(figsize=(12, 6), dpi=100, constrained_layout=False) self.gamma_canvas = FigureCanvasTkAgg(self.gamma_fig, master=container) canvas_widget = self.gamma_canvas.get_tk_widget() canvas_widget.pack(expand=True, fill=tk.BOTH) # 左侧:Gamma 曲线 self.gamma_ax = self.gamma_fig.add_axes([0.08, 0.12, 0.50, 0.78]) self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10) self.gamma_ax.set_ylabel("L_bar", fontsize=10) self.gamma_ax.set_xlim(0, 105) self.gamma_ax.set_ylim(0, 1.1) self.gamma_ax.grid(True, linestyle="--", alpha=0.3) self.gamma_ax.tick_params(labelsize=9) # 左侧提示(通用说明,不显示具体 Gamma 值) self.gamma_ax.text( 0.5, 0.5, "等待测试数据...\n\n" "将显示:\n" "• 实测曲线 (蓝色)\n" "• 理想 Gamma 曲线 (红色)\n\n" "Gamma 值由测试配置决定", ha="center", va="center", fontsize=10, color="gray", transform=self.gamma_ax.transAxes, bbox=dict( boxstyle="round,pad=1", facecolor="white", edgecolor="gray", alpha=0.8 ), ) # 右侧:数据表格 self.gamma_table_ax = self.gamma_fig.add_axes([0.62, 0.12, 0.35, 0.78]) self.gamma_table_ax.axis("off") # 4列表格数据 table_data = [ ["灰阶", "实测亮度\n(cd/m²)", "L_bar\n(计算)", "Gamma"], ["0%", "--", "--", "--"], ["10%", "--", "--", "--"], ["20%", "--", "--", "--"], ["30%", "--", "--", "--"], ["40%", "--", "--", "--"], ["50%", "--", "--", "--"], ["60%", "--", "--", "--"], ["70%", "--", "--", "--"], ["80%", "--", "--", "--"], ["90%", "--", "--", "--"], ["100%", "--", "--", "--"], ] table = self.gamma_table_ax.table( cellText=table_data, cellLoc="center", loc="center", colWidths=[0.18, 0.28, 0.27, 0.27], # ← 4列宽度 ) table.auto_set_font_size(False) table.set_fontsize(7.5) table.scale(1, 1.5) # 表头样式 for i in range(4): cell = table[(0, i)] cell.set_facecolor("#4472C4") cell.set_text_props(weight="bold", color="white", fontsize=7) # 数据行交替颜色 for i in range(1, len(table_data)): for j in range(4): cell = table[(i, j)] if i % 2 == 0: cell.set_facecolor("#E7E6E6") else: cell.set_facecolor("#FFFFFF") # 底部说明 self.gamma_table_ax.text( 0.5, 0.02, "表格说明:\n" "• 实测亮度: 色度计测量值 (cd/m²)\n" "• L_bar: 归一化亮度 (0-1)\n" "• Gamma: 实际 Gamma 值", ha="center", va="bottom", fontsize=7, color="gray", transform=self.gamma_table_ax.transAxes, bbox=dict( boxstyle="round,pad=0.5", facecolor="lightyellow", edgecolor="gray", alpha=0.8, ), ) self.gamma_fig.suptitle("Gamma曲线 + 数据表格", fontsize=12, y=0.98) self.gamma_canvas.draw() def init_eotf_chart(self): """初始化 EOTF 曲线图表(HDR 专用)- 左侧曲线 + 右侧表格(✅ 4列)""" container = ttk.Frame(self.eotf_chart_frame) container.pack(expand=True, fill=tk.BOTH) self.eotf_fig = plt.Figure(figsize=(12, 6), dpi=100, constrained_layout=False) self.eotf_canvas = FigureCanvasTkAgg(self.eotf_fig, master=container) canvas_widget = self.eotf_canvas.get_tk_widget() canvas_widget.pack(expand=True, fill=tk.BOTH) # 左侧:EOTF 曲线 self.eotf_ax = self.eotf_fig.add_axes([0.08, 0.12, 0.50, 0.78]) self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10) self.eotf_ax.set_ylabel("L_bar (归一化亮度)", fontsize=10) self.eotf_ax.set_xlim(0, 105) self.eotf_ax.set_ylim(0, 1.1) self.eotf_ax.grid(True, linestyle="--", alpha=0.3) self.eotf_ax.tick_params(labelsize=9) # 左侧提示 self.eotf_ax.text( 0.5, 0.5, "等待测试数据...\n\n将显示:\n• 实测 EOTF 曲线 (蓝色)\n• 理想 PQ 曲线 (红色)", ha="center", va="center", fontsize=11, color="gray", transform=self.eotf_ax.transAxes, bbox=dict( boxstyle="round,pad=1", facecolor="white", edgecolor="gray", alpha=0.8 ), ) # 右侧:数据表格 self.eotf_table_ax = self.eotf_fig.add_axes([0.62, 0.12, 0.35, 0.78]) self.eotf_table_ax.axis("off") # 4列表格数据 table_data = [ ["灰阶", "实测亮度\n(cd/m²)", "L_bar\n(计算)", "EOTF γ"], ["0%", "--", "--", "--"], ["10%", "--", "--", "--"], ["20%", "--", "--", "--"], ["30%", "--", "--", "--"], ["40%", "--", "--", "--"], ["50%", "--", "--", "--"], ["60%", "--", "--", "--"], ["70%", "--", "--", "--"], ["80%", "--", "--", "--"], ["90%", "--", "--", "--"], ["100%", "--", "--", "--"], ] table = self.eotf_table_ax.table( cellText=table_data, cellLoc="center", loc="center", colWidths=[0.18, 0.28, 0.27, 0.27], ) table.auto_set_font_size(False) table.set_fontsize(7.5) table.scale(1, 1.5) # 表头样式 for i in range(4): cell = table[(0, i)] cell.set_facecolor("#4472C4") cell.set_text_props(weight="bold", color="white", fontsize=7) # 数据行交替颜色 for i in range(1, len(table_data)): for j in range(4): cell = table[(i, j)] if i % 2 == 0: cell.set_facecolor("#E7E6E6") else: cell.set_facecolor("#FFFFFF") # 底部说明 self.eotf_table_ax.text( 0.5, 0.02, "表格说明:\n" "• 实测亮度: 色度计测量值 (cd/m²)\n" "• L_bar: 归一化亮度 (0-1)\n" "• EOTF γ: HDR 实际 Gamma 值", ha="center", va="bottom", fontsize=7, color="gray", transform=self.eotf_table_ax.transAxes, bbox=dict( boxstyle="round,pad=0.5", facecolor="lightyellow", edgecolor="gray", alpha=0.8, ), ) self.eotf_fig.suptitle("EOTF 曲线 + 数据表格", fontsize=12, y=0.98) self.eotf_canvas.draw() def init_cct_chart(self): """初始化色度坐标图表 - 正向横坐标,标题居中最上方""" container = ttk.Frame(self.cct_chart_frame) container.pack(expand=True) self.cct_fig = plt.Figure(figsize=(8, 6), dpi=100, tight_layout=False) self.cct_canvas = FigureCanvasTkAgg(self.cct_fig, master=container) canvas_widget = self.cct_canvas.get_tk_widget() canvas_widget.pack() canvas_widget.config(width=800, height=600) canvas_widget.pack_propagate(False) self.cct_ax1 = self.cct_fig.add_subplot(211) self.cct_ax2 = self.cct_fig.add_subplot(212) # 上图:x coordinates self.cct_ax1.set_xlabel("灰阶 (%)", fontsize=9) self.cct_ax1.set_ylabel("CIE x", fontsize=9) self.cct_ax1.set_xlim(0, 105) self.cct_ax1.set_ylim(0.25, 0.35) self.cct_ax1.grid(True, linestyle="--", alpha=0.3) self.cct_ax1.tick_params(labelsize=8) # 下图:y coordinates self.cct_ax2.set_xlabel("灰阶 (%)", fontsize=9) self.cct_ax2.set_ylabel("CIE y", fontsize=9) self.cct_ax2.set_xlim(0, 105) self.cct_ax2.set_ylim(0.25, 0.35) self.cct_ax2.grid(True, linestyle="--", alpha=0.3) self.cct_ax2.tick_params(labelsize=8) # 调整标题位置:y=0.985(比色域/Gamma略高) self.cct_fig.suptitle("色度一致性测试", fontsize=12, y=0.985) self.cct_fig.subplots_adjust( left=0.12, right=0.88, top=0.90, bottom=0.08, hspace=0.25, ) self.cct_canvas.draw() def init_contrast_chart(self): """初始化对比度图表 - 固定大小,居中显示""" container = ttk.Frame(self.contrast_chart_frame) container.pack(expand=True) self.contrast_fig = plt.Figure( figsize=(6, 6), dpi=100, tight_layout=False, ) self.contrast_canvas = FigureCanvasTkAgg(self.contrast_fig, master=container) canvas_widget = self.contrast_canvas.get_tk_widget() canvas_widget.pack() canvas_widget.config(width=600, height=600) canvas_widget.pack_propagate(False) self.contrast_ax = self.contrast_fig.add_subplot(111) self.contrast_ax.set_xlim(0, 1) self.contrast_ax.set_ylim(0, 1) self.contrast_ax.axis("off") # 调整标题位置:y=0.985 self.contrast_fig.suptitle("对比度测试", fontsize=12, y=0.985) self.contrast_fig.subplots_adjust( left=0.02, right=0.98, top=0.90, bottom=0.02, ) self.contrast_canvas.draw() def init_accuracy_chart(self): """初始化色准图表 - 固定大小,居中显示""" container = ttk.Frame(self.accuracy_chart_frame) container.pack(expand=True) self.accuracy_fig = plt.Figure( figsize=(10, 6), dpi=100, tight_layout=False, ) self.accuracy_canvas = FigureCanvasTkAgg(self.accuracy_fig, master=container) canvas_widget = self.accuracy_canvas.get_tk_widget() canvas_widget.pack() canvas_widget.config(width=1000, height=600) canvas_widget.pack_propagate(False) self.accuracy_ax = self.accuracy_fig.add_subplot(111) self.accuracy_ax.set_xlim(0, 1) self.accuracy_ax.set_ylim(0, 1) self.accuracy_ax.axis("off") # 调整标题位置 self.accuracy_fig.suptitle("色准测试", fontsize=12, y=0.985) self.accuracy_fig.subplots_adjust( left=0.05, right=0.95, top=0.90, bottom=0.05, ) self.accuracy_canvas.draw() def clear_chart(self): """清空所有图表""" # ========== 1. 清空色域图表 ========== if hasattr(self, "gamut_ax_xy") and hasattr(self, "gamut_ax_uv"): # 清空XY图 self.gamut_ax_xy.clear() self.gamut_ax_xy.set_xlim(0, 600) self.gamut_ax_xy.set_ylim(600, 0) self.gamut_ax_xy.axis("off") self.gamut_ax_xy.set_clip_on(False) # 清空UV图 self.gamut_ax_uv.clear() self.gamut_ax_uv.set_xlim(0, 600) self.gamut_ax_uv.set_ylim(600, 0) self.gamut_ax_uv.axis("off") self.gamut_ax_uv.set_clip_on(False) self.gamut_fig.suptitle("色域测试", fontsize=12, y=0.98) self.gamut_canvas.draw() # ========== 2. 清空Gamma图表(4列 + 通用说明)========== if hasattr(self, "gamma_ax") and hasattr(self, "gamma_table_ax"): # 清空左侧曲线 self.gamma_ax.clear() self.gamma_ax.set_xlim(0, 105) self.gamma_ax.set_ylim(0, 1.1) self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10) self.gamma_ax.set_ylabel("L_bar", fontsize=10) self.gamma_ax.grid(True, linestyle="--", alpha=0.3) self.gamma_ax.tick_params(labelsize=9) # 左侧提示 self.gamma_ax.text( 0.5, 0.5, "等待测试数据...\n\n" "将显示:\n" "• 实测曲线 (蓝色)\n" "• 理想 Gamma 曲线 (红色)\n\n" "Gamma 值由测试配置决定", ha="center", va="center", fontsize=10, color="gray", transform=self.gamma_ax.transAxes, bbox=dict( boxstyle="round,pad=1", facecolor="white", edgecolor="gray", alpha=0.8, ), ) # 清空右侧表格 self.gamma_table_ax.clear() self.gamma_table_ax.axis("off") # 4列表格 table_data = [ ["灰阶", "实测亮度\n(cd/m²)", "L_bar\n(计算)", "Gamma"], ["0%", "--", "--", "--"], ["10%", "--", "--", "--"], ["20%", "--", "--", "--"], ["30%", "--", "--", "--"], ["40%", "--", "--", "--"], ["50%", "--", "--", "--"], ["60%", "--", "--", "--"], ["70%", "--", "--", "--"], ["80%", "--", "--", "--"], ["90%", "--", "--", "--"], ["100%", "--", "--", "--"], ] table = self.gamma_table_ax.table( cellText=table_data, cellLoc="center", loc="center", colWidths=[0.18, 0.28, 0.27, 0.27], ) table.auto_set_font_size(False) table.set_fontsize(7.5) table.scale(1, 1.5) # 表头样式 for i in range(4): cell = table[(0, i)] cell.set_facecolor("#4472C4") cell.set_text_props(weight="bold", color="white", fontsize=7) # 数据行交替颜色 for i in range(1, len(table_data)): for j in range(4): cell = table[(i, j)] if i % 2 == 0: cell.set_facecolor("#E7E6E6") else: cell.set_facecolor("#FFFFFF") # 底部说明 self.gamma_table_ax.text( 0.5, 0.02, "表格说明:\n" "• 实测亮度: 色度计测量值 (cd/m²)\n" "• L_bar: 归一化亮度 (0-1)\n" "• Gamma: 实际 Gamma 值", ha="center", va="bottom", fontsize=7, color="gray", transform=self.gamma_table_ax.transAxes, bbox=dict( boxstyle="round,pad=0.5", facecolor="lightyellow", edgecolor="gray", alpha=0.8, ), ) self.gamma_fig.suptitle("Gamma曲线 + 数据表格", fontsize=12, y=0.98) self.gamma_canvas.draw() # ========== 3. 清空EOTF图表(4列)========== if hasattr(self, "eotf_ax") and hasattr(self, "eotf_table_ax"): # 清空左侧曲线 self.eotf_ax.clear() self.eotf_ax.set_xlim(0, 105) self.eotf_ax.set_ylim(0, 1.1) self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10) self.eotf_ax.set_ylabel("L_bar (归一化亮度)", fontsize=10) self.eotf_ax.grid(True, linestyle="--", alpha=0.3) self.eotf_ax.tick_params(labelsize=9) # 左侧提示 self.eotf_ax.text( 0.5, 0.5, "等待测试数据...\n\n将显示:\n• 实测 EOTF 曲线 (蓝色)\n• 理想 PQ 曲线 (红色)", ha="center", va="center", fontsize=11, color="gray", transform=self.eotf_ax.transAxes, bbox=dict( boxstyle="round,pad=1", facecolor="white", edgecolor="gray", alpha=0.8, ), ) # 清空右侧表格 self.eotf_table_ax.clear() self.eotf_table_ax.axis("off") # 4列表格 table_data = [ ["灰阶", "实测亮度\n(cd/m²)", "L_bar\n(计算)", "EOTF γ"], ["0%", "--", "--", "--"], ["10%", "--", "--", "--"], ["20%", "--", "--", "--"], ["30%", "--", "--", "--"], ["40%", "--", "--", "--"], ["50%", "--", "--", "--"], ["60%", "--", "--", "--"], ["70%", "--", "--", "--"], ["80%", "--", "--", "--"], ["90%", "--", "--", "--"], ["100%", "--", "--", "--"], ] table = self.eotf_table_ax.table( cellText=table_data, cellLoc="center", loc="center", colWidths=[0.18, 0.28, 0.27, 0.27], ) table.auto_set_font_size(False) table.set_fontsize(7.5) table.scale(1, 1.5) # 表头样式 for i in range(4): cell = table[(0, i)] cell.set_facecolor("#4472C4") cell.set_text_props(weight="bold", color="white", fontsize=7) # 数据行交替颜色 for i in range(1, len(table_data)): for j in range(4): cell = table[(i, j)] if i % 2 == 0: cell.set_facecolor("#E7E6E6") else: cell.set_facecolor("#FFFFFF") # 底部说明 self.eotf_table_ax.text( 0.5, 0.02, "表格说明:\n" "• 实测亮度: 色度计测量值 (cd/m²)\n" "• L_bar: 归一化亮度 (0-1)\n" "• EOTF γ: HDR 实际 Gamma 值", ha="center", va="bottom", fontsize=7, color="gray", transform=self.eotf_table_ax.transAxes, bbox=dict( boxstyle="round,pad=0.5", facecolor="lightyellow", edgecolor="gray", alpha=0.8, ), ) self.eotf_fig.suptitle("EOTF 曲线 + 数据表格", fontsize=12, y=0.98) self.eotf_canvas.draw() # ========== 4. 清空色度图表 ========== if hasattr(self, "cct_ax1") and hasattr(self, "cct_ax2"): # 上图:x coordinates self.cct_ax1.clear() self.cct_ax1.set_xlabel("灰阶 (%)", fontsize=9) self.cct_ax1.set_ylabel("CIE x", fontsize=9) self.cct_ax1.set_xlim(0, 105) self.cct_ax1.set_ylim(0.25, 0.35) self.cct_ax1.grid(True, linestyle="--", alpha=0.3) self.cct_ax1.tick_params(labelsize=8) # 下图:y coordinates self.cct_ax2.clear() self.cct_ax2.set_xlabel("灰阶 (%)", fontsize=9) self.cct_ax2.set_ylabel("CIE y", fontsize=9) self.cct_ax2.set_xlim(0, 105) self.cct_ax2.set_ylim(0.25, 0.35) self.cct_ax2.grid(True, linestyle="--", alpha=0.3) self.cct_ax2.tick_params(labelsize=8) self.cct_fig.suptitle("色度一致性测试", fontsize=12, y=0.985) # 重置布局 self.cct_fig.subplots_adjust( left=0.12, right=0.88, top=0.90, bottom=0.08, hspace=0.25, ) self.cct_canvas.draw() # ========== 5. 清空对比度图表 ========== if hasattr(self, "contrast_ax"): self.contrast_ax.clear() self.contrast_ax.set_xlim(0, 1) self.contrast_ax.set_ylim(0, 1) self.contrast_ax.axis("off") self.contrast_fig.suptitle("对比度测试", fontsize=12, y=0.985) # 重置布局 self.contrast_fig.subplots_adjust( left=0.02, right=0.98, top=0.90, bottom=0.02, ) self.contrast_canvas.draw() # ========== 6. 清空色准图表 ========== if hasattr(self, "accuracy_ax"): self.accuracy_ax.clear() self.accuracy_ax.set_xlim(0, 1) self.accuracy_ax.set_ylim(0, 1) self.accuracy_ax.axis("off") # 标题 self.accuracy_fig.suptitle("色准测试", fontsize=12, y=0.985) # 重置布局 self.accuracy_fig.subplots_adjust( left=0.05, right=0.95, top=0.90, bottom=0.05, ) self.accuracy_canvas.draw() def update_chart_tabs_state(self): """根据测试项目复选框状态动态增删图表 Tab(保持规范顺序)。 - 色域 / Gamma 或 EOTF / 色度一致性 / 对比度 / 色准 全部走动态 add/forget - Gamma 与 EOTF 二选一,由 current_test_type 决定 - 屏模组测试强制隐藏色准 Tab - 客户模板 Tab 由 change_test_type 独立管理,这里不动 """ if not hasattr(self, "chart_notebook"): return selected_items = self.get_selected_test_items() current_test_type = self.config.current_test_type # 根据测试类型决定 gamma/eotf 显示哪一个 if current_test_type == "hdr_movie": gamma_like_frame = self.eotf_chart_frame gamma_like_text = "EOTF 曲线" gamma_like_other = self.gamma_chart_frame else: gamma_like_frame = self.gamma_chart_frame gamma_like_text = "Gamma 曲线" gamma_like_other = self.eotf_chart_frame want_gamut = "gamut" in selected_items want_gamma_like = "gamma" in selected_items or "eotf" in selected_items want_cct = "cct" in selected_items want_contrast = "contrast" in selected_items want_accuracy = ( "accuracy" in selected_items and current_test_type != "screen_module" ) # 规范顺序:色域 → Gamma/EOTF → 色度一致性 → 对比度 → 色准 spec = [ (want_gamut, self.gamut_chart_frame, "色域图"), (want_gamma_like, gamma_like_frame, gamma_like_text), (want_cct, self.cct_chart_frame, "色度一致性"), (want_contrast, self.contrast_chart_frame, "对比度"), (want_accuracy, self.accuracy_chart_frame, "色准"), ] try: # 始终先把"另一个" gamma/eotf frame 从 Notebook 移除,保持互斥 current_ids = list(self.chart_notebook.tabs()) if str(gamma_like_other) in current_ids: self.chart_notebook.forget(gamma_like_other) # 按规范顺序处理 add/forget for idx_in_spec, (want, frame, text) in enumerate(spec): fid = str(frame) present = fid in self.chart_notebook.tabs() if want and not present: # 统计该 frame 在 spec 中前面、当前实际存在的 tab 数 → 插入位置 current_ids = list(self.chart_notebook.tabs()) pos = sum( 1 for pre_want, pre_frame, _ in spec[:idx_in_spec] if str(pre_frame) in current_ids ) try: self.chart_notebook.insert(pos, frame, text=text) except Exception: # fallback:尾部 add self.chart_notebook.add(frame, text=text) elif not want and present: self.chart_notebook.forget(frame) except Exception as e: if hasattr(self, "log_gui"): self.log_gui.log(f"更新Tab状态失败: {str(e)}") def create_result_chart_frame(self): """创建结果图表区域 - 6个独立Tab(Gamma 和 EOTF 分离)""" # 创建Notebook用于图表切换 self.chart_notebook = ttk.Notebook(self.result_frame) self.chart_notebook.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) # ========== 创建6个独立的Tab页面 ========== # 1. 色域图页面 self.gamut_chart_frame = ttk.Frame(self.chart_notebook) # 2. Gamma图页面(SDR/屏模组使用) self.gamma_chart_frame = ttk.Frame(self.chart_notebook) # 3. EOTF图页面(HDR专用) self.eotf_chart_frame = ttk.Frame(self.chart_notebook) # 4. 色度一致性页面 self.cct_chart_frame = ttk.Frame(self.chart_notebook) # 5. 对比度页面 self.contrast_chart_frame = ttk.Frame(self.chart_notebook) # 6. 色准页面 self.accuracy_chart_frame = ttk.Frame(self.chart_notebook) # 7. 客户模板结果页面 self.custom_template_tab_frame = ttk.Frame(self.chart_notebook) # ========== 添加到Notebook(初始只添加前5个)========== self.chart_notebook.add(self.gamut_chart_frame, text="色域图") self.chart_notebook.add(self.gamma_chart_frame, text="Gamma曲线") # ← EOTF 不添加,由 change_test_type() 动态控制 self.chart_notebook.add(self.cct_chart_frame, text="色度一致性") self.chart_notebook.add(self.contrast_chart_frame, text="对比度") self.chart_notebook.add(self.accuracy_chart_frame, text="色准") # 初始化六个独立的图表 self.init_gamut_chart() self.init_gamma_chart() self.init_eotf_chart() self.init_cct_chart() self.init_contrast_chart() self.init_accuracy_chart() # 绑定Tab切换事件 self.chart_notebook.bind("<>", self.on_chart_tab_changed) # ==================== ✅ 在图表下方创建单步调试面板 ==================== self.debug_container = ttk.LabelFrame( self.result_frame, # ← 放在 result_frame 内,图表正下方 text="🔧 单步调试", padding=10, ) # 默认不显示 # 创建单步调试面板实例 self.debug_panel = PQDebugPanel(self.debug_container, self) self.log_gui.log("✓ 单步调试面板已创建(放在测试结果图表下方)") def on_chart_tab_changed(self, event): """Tab切换时的事件处理""" try: self._last_tab_index = self.chart_notebook.index( self.chart_notebook.select() ) except Exception as e: self.log_gui.log(f"Tab切换事件处理失败: {str(e)}")