Files
pqAutomationApp/app/views/pq_debug_panel.py

1231 lines
44 KiB
Python
Raw Normal View History

2026-04-16 16:51:05 +08:00
"""
PQ 单步调试面板
支持屏模组SDRHDR 三种测试类型的单步调试功能
"""
import ttkbootstrap as ttk
import tkinter as tk
from tkinter import messagebox
import threading
import time
class PQDebugPanel:
"""PQ 单步调试面板 - 支持 Gamma/EOTF/色准单步测试"""
def __init__(self, parent, app):
"""
初始化单步调试面板
Args:
parent: 父容器
app: 主应用程序实例用于访问设备和配置
"""
self.parent = parent
self.app = app
# 当前测试类型和项目
self.current_test_type = None # screen_module / sdr_movie / hdr_movie
self.current_test_item = None # gamma / eotf / accuracy
# 测试完成标志
self.test_completed = False
# 原始测试数据(用于对比)
self.original_data = {}
# ==================== ✅ 创建主容器并自动 pack ====================
self.main_container = ttk.Frame(parent)
self.main_container.pack(fill=tk.BOTH, expand=True)
# 创建 LabelFrame 放在 main_container 中
self.main_frame = ttk.LabelFrame(
self.main_container, text="单步调试", padding=10
)
self.main_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# 创建三个独立的调试面板
self.create_screen_module_panel()
self.create_sdr_panel()
self.create_hdr_panel()
# 默认隐藏所有面板
self.hide_all_panels()
# ==================== 创建三个独立面板 ====================
def create_screen_module_panel(self):
"""创建屏模组单步调试面板"""
self.screen_frame = ttk.LabelFrame(
self.main_frame, text="屏模组 - 单步调试", padding=10
)
# Notebook 用于切换 Gamma 和 RGB 调试
self.screen_notebook = ttk.Notebook(self.screen_frame)
self.screen_notebook.pack(fill=tk.BOTH, expand=True)
# ========== Gamma 调试页 ==========
self.screen_gamma_frame = ttk.Frame(self.screen_notebook, padding=10)
self.screen_notebook.add(self.screen_gamma_frame, text="Gamma 调试")
ttk.Label(
self.screen_gamma_frame,
text="测试完成后可用,选择灰阶进行单步调试",
font=("SimHei", 9),
foreground="gray",
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
# 灰阶选择
ttk.Label(self.screen_gamma_frame, text="选择灰阶:").grid(
row=1, column=0, sticky=tk.W, padx=5, pady=5
)
self.screen_gray_var = tk.StringVar(value="0%")
self.screen_gray_combo = ttk.Combobox(
self.screen_gamma_frame,
textvariable=self.screen_gray_var,
values=[f"{i}%" for i in [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]],
state="disabled",
width=12,
)
self.screen_gray_combo.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
# 测试按钮
self.screen_test_btn = ttk.Button(
self.screen_gamma_frame,
text="单步测试",
command=lambda: self.run_single_step("screen_module", "gamma"),
state=tk.DISABLED,
bootstyle="success",
)
self.screen_test_btn.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)
# 对比结果显示区域
self.screen_result_frame = ttk.Frame(self.screen_gamma_frame)
self.screen_result_frame.grid(
row=2, column=0, columnspan=3, sticky="nsew", pady=10
)
# 创建对比表格
columns = ("项目", "原始测试", "单步测试", "差异")
self.screen_result_tree = ttk.Treeview(
self.screen_result_frame,
columns=columns,
show="headings",
height=6,
)
for col in columns:
self.screen_result_tree.heading(col, text=col)
self.screen_result_tree.column(col, width=120, anchor=tk.CENTER)
self.screen_result_tree.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(
self.screen_result_frame,
orient=tk.VERTICAL,
command=self.screen_result_tree.yview,
)
self.screen_result_tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# ========== RGB 调试页 ==========
self.screen_rgb_frame = ttk.Frame(self.screen_notebook, padding=10)
self.screen_notebook.add(self.screen_rgb_frame, text="RGB 调试")
ttk.Label(
self.screen_rgb_frame,
text="测试完成后可用,选择颜色进行单步调试",
font=("SimHei", 9),
foreground="gray",
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
# RGB 颜色选择
ttk.Label(self.screen_rgb_frame, text="选择颜色:").grid(
row=1, column=0, sticky=tk.W, padx=5, pady=5
)
self.screen_rgb_var = tk.StringVar(value="Red")
self.screen_rgb_combo = ttk.Combobox(
self.screen_rgb_frame,
textvariable=self.screen_rgb_var,
values=["Red", "Green", "Blue"],
state="disabled",
width=12,
)
self.screen_rgb_combo.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
self.screen_rgb_test_btn = ttk.Button(
self.screen_rgb_frame,
text="单步测试",
command=lambda: self.run_single_step("screen_module", "rgb"),
state=tk.DISABLED,
bootstyle="info",
)
self.screen_rgb_test_btn.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)
# RGB 对比结果
self.screen_rgb_result_frame = ttk.Frame(self.screen_rgb_frame)
self.screen_rgb_result_frame.grid(
row=2, column=0, columnspan=3, sticky="nsew", pady=10
)
columns = ("项目", "原始测试", "单步测试", "差异")
self.screen_rgb_result_tree = ttk.Treeview(
self.screen_rgb_result_frame,
columns=columns,
show="headings",
height=6,
)
for col in columns:
self.screen_rgb_result_tree.heading(col, text=col)
self.screen_rgb_result_tree.column(col, width=120, anchor=tk.CENTER)
self.screen_rgb_result_tree.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(
self.screen_rgb_result_frame,
orient=tk.VERTICAL,
command=self.screen_rgb_result_tree.yview,
)
self.screen_rgb_result_tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
def create_sdr_panel(self):
"""创建 SDR 单步调试面板"""
self.sdr_frame = ttk.LabelFrame(
self.main_frame, text="SDR Movie - 单步调试", padding=10
)
# Notebook 用于切换 Gamma 和色准
self.sdr_notebook = ttk.Notebook(self.sdr_frame)
self.sdr_notebook.pack(fill=tk.BOTH, expand=True)
# ========== Gamma 调试页 ==========
self.sdr_gamma_frame = ttk.Frame(self.sdr_notebook, padding=10)
self.sdr_notebook.add(self.sdr_gamma_frame, text="Gamma 调试")
ttk.Label(
self.sdr_gamma_frame,
text="测试完成后可用,选择灰阶进行单步调试",
font=("SimHei", 9),
foreground="gray",
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
ttk.Label(self.sdr_gamma_frame, text="选择灰阶:").grid(
row=1, column=0, sticky=tk.W, padx=5, pady=5
)
self.sdr_gray_var = tk.StringVar(value="0%")
self.sdr_gray_combo = ttk.Combobox(
self.sdr_gamma_frame,
textvariable=self.sdr_gray_var,
values=[f"{i}%" for i in [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]],
state="disabled",
width=12,
)
self.sdr_gray_combo.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
self.sdr_gamma_test_btn = ttk.Button(
self.sdr_gamma_frame,
text="单步测试",
command=lambda: self.run_single_step("sdr_movie", "gamma"),
state=tk.DISABLED,
bootstyle="success",
)
self.sdr_gamma_test_btn.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)
# 对比结果
self.sdr_gamma_result_frame = ttk.Frame(self.sdr_gamma_frame)
self.sdr_gamma_result_frame.grid(
row=2, column=0, columnspan=3, sticky="nsew", pady=10
)
columns = ("项目", "原始测试", "单步测试", "差异")
self.sdr_gamma_result_tree = ttk.Treeview(
self.sdr_gamma_result_frame,
columns=columns,
show="headings",
height=6,
)
for col in columns:
self.sdr_gamma_result_tree.heading(col, text=col)
self.sdr_gamma_result_tree.column(col, width=120, anchor=tk.CENTER)
self.sdr_gamma_result_tree.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(
self.sdr_gamma_result_frame,
orient=tk.VERTICAL,
command=self.sdr_gamma_result_tree.yview,
)
self.sdr_gamma_result_tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# ========== 色准调试页 ==========
self.sdr_accuracy_frame = ttk.Frame(self.sdr_notebook, padding=10)
self.sdr_notebook.add(self.sdr_accuracy_frame, text="色准调试")
ttk.Label(
self.sdr_accuracy_frame,
text="测试完成后可用,选择色块进行单步调试",
font=("SimHei", 9),
foreground="gray",
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
ttk.Label(self.sdr_accuracy_frame, text="选择色块:").grid(
row=1, column=0, sticky=tk.W, padx=5, pady=5
)
self.sdr_color_var = tk.StringVar(value="White")
self.sdr_color_combo = ttk.Combobox(
self.sdr_accuracy_frame,
textvariable=self.sdr_color_var,
values=self.get_29_color_names(),
state="disabled",
width=20,
)
self.sdr_color_combo.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
self.sdr_accuracy_test_btn = ttk.Button(
self.sdr_accuracy_frame,
text="单步测试",
command=lambda: self.run_single_step("sdr_movie", "accuracy"),
state=tk.DISABLED,
bootstyle="warning",
)
self.sdr_accuracy_test_btn.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)
# 对比结果
self.sdr_accuracy_result_frame = ttk.Frame(self.sdr_accuracy_frame)
self.sdr_accuracy_result_frame.grid(
row=2, column=0, columnspan=3, sticky="nsew", pady=10
)
columns = ("项目", "原始测试", "单步测试", "差异")
self.sdr_accuracy_result_tree = ttk.Treeview(
self.sdr_accuracy_result_frame,
columns=columns,
show="headings",
height=6,
)
for col in columns:
self.sdr_accuracy_result_tree.heading(col, text=col)
self.sdr_accuracy_result_tree.column(col, width=120, anchor=tk.CENTER)
self.sdr_accuracy_result_tree.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(
self.sdr_accuracy_result_frame,
orient=tk.VERTICAL,
command=self.sdr_accuracy_result_tree.yview,
)
self.sdr_accuracy_result_tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# ========== RGB 调试页 ==========
self.sdr_rgb_frame = ttk.Frame(self.sdr_notebook, padding=10)
self.sdr_notebook.add(self.sdr_rgb_frame, text="RGB 调试")
ttk.Label(
self.sdr_rgb_frame,
text="测试完成后可用,选择颜色进行单步调试",
font=("SimHei", 9),
foreground="gray",
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
# RGB 颜色选择
ttk.Label(self.sdr_rgb_frame, text="选择颜色:").grid(
row=1, column=0, sticky=tk.W, padx=5, pady=5
)
self.sdr_rgb_var = tk.StringVar(value="Red")
self.sdr_rgb_combo = ttk.Combobox(
self.sdr_rgb_frame,
textvariable=self.sdr_rgb_var,
values=["Red", "Green", "Blue"],
state="disabled",
width=12,
)
self.sdr_rgb_combo.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
self.sdr_rgb_test_btn = ttk.Button(
self.sdr_rgb_frame,
text="单步测试",
command=lambda: self.run_single_step("sdr_movie", "rgb"),
state=tk.DISABLED,
bootstyle="info",
)
self.sdr_rgb_test_btn.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)
# RGB 对比结果
self.sdr_rgb_result_frame = ttk.Frame(self.sdr_rgb_frame)
self.sdr_rgb_result_frame.grid(
row=2, column=0, columnspan=3, sticky="nsew", pady=10
)
columns = ("项目", "原始测试", "单步测试", "差异")
self.sdr_rgb_result_tree = ttk.Treeview(
self.sdr_rgb_result_frame,
columns=columns,
show="headings",
height=6,
)
for col in columns:
self.sdr_rgb_result_tree.heading(col, text=col)
self.sdr_rgb_result_tree.column(col, width=120, anchor=tk.CENTER)
self.sdr_rgb_result_tree.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(
self.sdr_rgb_result_frame,
orient=tk.VERTICAL,
command=self.sdr_rgb_result_tree.yview,
)
self.sdr_rgb_result_tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
def create_hdr_panel(self):
"""创建 HDR 单步调试面板"""
self.hdr_frame = ttk.LabelFrame(
self.main_frame, text="HDR Movie - 单步调试", padding=10
)
# Notebook 用于切换 EOTF 和色准
self.hdr_notebook = ttk.Notebook(self.hdr_frame)
self.hdr_notebook.pack(fill=tk.BOTH, expand=True)
# ========== EOTF 调试页 ==========
self.hdr_eotf_frame = ttk.Frame(self.hdr_notebook, padding=10)
self.hdr_notebook.add(self.hdr_eotf_frame, text="EOTF 调试")
ttk.Label(
self.hdr_eotf_frame,
text="测试完成后可用,选择灰阶进行单步调试",
font=("SimHei", 9),
foreground="gray",
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
ttk.Label(self.hdr_eotf_frame, text="选择灰阶:").grid(
row=1, column=0, sticky=tk.W, padx=5, pady=5
)
self.hdr_gray_var = tk.StringVar(value="0%")
self.hdr_gray_combo = ttk.Combobox(
self.hdr_eotf_frame,
textvariable=self.hdr_gray_var,
values=[f"{i}%" for i in [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]],
state="disabled",
width=12,
)
self.hdr_gray_combo.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
self.hdr_eotf_test_btn = ttk.Button(
self.hdr_eotf_frame,
text="单步测试",
command=lambda: self.run_single_step("hdr_movie", "eotf"),
state=tk.DISABLED,
bootstyle="success",
)
self.hdr_eotf_test_btn.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)
# 对比结果
self.hdr_eotf_result_frame = ttk.Frame(self.hdr_eotf_frame)
self.hdr_eotf_result_frame.grid(
row=2, column=0, columnspan=3, sticky="nsew", pady=10
)
columns = ("项目", "原始测试", "单步测试", "差异")
self.hdr_eotf_result_tree = ttk.Treeview(
self.hdr_eotf_result_frame,
columns=columns,
show="headings",
height=6,
)
for col in columns:
self.hdr_eotf_result_tree.heading(col, text=col)
self.hdr_eotf_result_tree.column(col, width=120, anchor=tk.CENTER)
self.hdr_eotf_result_tree.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(
self.hdr_eotf_result_frame,
orient=tk.VERTICAL,
command=self.hdr_eotf_result_tree.yview,
)
self.hdr_eotf_result_tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# ========== 色准调试页 ==========
self.hdr_accuracy_frame = ttk.Frame(self.hdr_notebook, padding=10)
self.hdr_notebook.add(self.hdr_accuracy_frame, text="色准调试")
ttk.Label(
self.hdr_accuracy_frame,
text="测试完成后可用,选择色块进行单步调试",
font=("SimHei", 9),
foreground="gray",
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
ttk.Label(self.hdr_accuracy_frame, text="选择色块:").grid(
row=1, column=0, sticky=tk.W, padx=5, pady=5
)
self.hdr_color_var = tk.StringVar(value="White")
self.hdr_color_combo = ttk.Combobox(
self.hdr_accuracy_frame,
textvariable=self.hdr_color_var,
values=self.get_29_color_names(),
state="disabled",
width=20,
)
self.hdr_color_combo.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
self.hdr_accuracy_test_btn = ttk.Button(
self.hdr_accuracy_frame,
text="单步测试",
command=lambda: self.run_single_step("hdr_movie", "accuracy"),
state=tk.DISABLED,
bootstyle="warning",
)
self.hdr_accuracy_test_btn.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)
# 对比结果
self.hdr_accuracy_result_frame = ttk.Frame(self.hdr_accuracy_frame)
self.hdr_accuracy_result_frame.grid(
row=2, column=0, columnspan=3, sticky="nsew", pady=10
)
columns = ("项目", "原始测试", "单步测试", "差异")
self.hdr_accuracy_result_tree = ttk.Treeview(
self.hdr_accuracy_result_frame,
columns=columns,
show="headings",
height=6,
)
for col in columns:
self.hdr_accuracy_result_tree.heading(col, text=col)
self.hdr_accuracy_result_tree.column(col, width=120, anchor=tk.CENTER)
self.hdr_accuracy_result_tree.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(
self.hdr_accuracy_result_frame,
orient=tk.VERTICAL,
command=self.hdr_accuracy_result_tree.yview,
)
self.hdr_accuracy_result_tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# ========== RGB 调试页 ==========
self.hdr_rgb_frame = ttk.Frame(self.hdr_notebook, padding=10)
self.hdr_notebook.add(self.hdr_rgb_frame, text="RGB 调试")
ttk.Label(
self.hdr_rgb_frame,
text="测试完成后可用,选择颜色进行单步调试",
font=("SimHei", 9),
foreground="gray",
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
# RGB 颜色选择
ttk.Label(self.hdr_rgb_frame, text="选择颜色:").grid(
row=1, column=0, sticky=tk.W, padx=5, pady=5
)
self.hdr_rgb_var = tk.StringVar(value="Red")
self.hdr_rgb_combo = ttk.Combobox(
self.hdr_rgb_frame,
textvariable=self.hdr_rgb_var,
values=["Red", "Green", "Blue"],
state="disabled",
width=12,
)
self.hdr_rgb_combo.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
self.hdr_rgb_test_btn = ttk.Button(
self.hdr_rgb_frame,
text="单步测试",
command=lambda: self.run_single_step("hdr_movie", "rgb"),
state=tk.DISABLED,
bootstyle="info",
)
self.hdr_rgb_test_btn.grid(row=1, column=2, sticky=tk.W, padx=5, pady=5)
# RGB 对比结果
self.hdr_rgb_result_frame = ttk.Frame(self.hdr_rgb_frame)
self.hdr_rgb_result_frame.grid(
row=2, column=0, columnspan=3, sticky="nsew", pady=10
)
columns = ("项目", "原始测试", "单步测试", "差异")
self.hdr_rgb_result_tree = ttk.Treeview(
self.hdr_rgb_result_frame,
columns=columns,
show="headings",
height=6,
)
for col in columns:
self.hdr_rgb_result_tree.heading(col, text=col)
self.hdr_rgb_result_tree.column(col, width=120, anchor=tk.CENTER)
self.hdr_rgb_result_tree.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(
self.hdr_rgb_result_frame,
orient=tk.VERTICAL,
command=self.hdr_rgb_result_tree.yview,
)
self.hdr_rgb_result_tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# ==================== 面板显示控制 ====================
def hide_all_panels(self):
"""隐藏所有面板"""
self.screen_frame.pack_forget()
self.sdr_frame.pack_forget()
self.hdr_frame.pack_forget()
def show_panel(self, test_type):
"""根据测试类型显示对应面板"""
self.hide_all_panels()
if test_type == "screen_module":
self.screen_frame.pack(fill=tk.BOTH, expand=True)
self.app.log_gui.log("✓ 显示屏模组调试面板")
elif test_type == "sdr_movie":
self.sdr_frame.pack(fill=tk.BOTH, expand=True)
self.app.log_gui.log("✓ 显示 SDR 调试面板")
elif test_type == "hdr_movie":
self.hdr_frame.pack(fill=tk.BOTH, expand=True)
self.app.log_gui.log("✓ 显示 HDR 调试面板")
# ==================== 启用/禁用控制 ====================
def enable_debug(self, test_type, test_item, original_data):
"""
测试完成后启用单步调试
Args:
test_type: screen_module / sdr_movie / hdr_movie
test_item: gamma / eotf / accuracy / rgb
"""
self.current_test_type = test_type
self.current_test_item = test_item
self.test_completed = True
self.original_data[f"{test_type}_{test_item}"] = original_data
# 显示对应面板
self.show_panel(test_type)
# 启用对应控件
if test_type == "screen_module":
if test_item == "gamma":
self.screen_gray_combo.config(state="readonly")
self.screen_test_btn.config(state=tk.NORMAL)
self.app.log_gui.log("✓ 屏模组 Gamma 单步调试已启用")
elif test_item == "rgb":
self.screen_rgb_combo.config(state="readonly")
self.screen_rgb_test_btn.config(state=tk.NORMAL)
self.app.log_gui.log("✓ 屏模组 RGB 单步调试已启用")
elif test_type == "sdr_movie":
if test_item == "gamma":
self.sdr_gray_combo.config(state="readonly")
self.sdr_gamma_test_btn.config(state=tk.NORMAL)
self.app.log_gui.log("✓ SDR Gamma 单步调试已启用")
elif test_item == "accuracy":
self.sdr_color_combo.config(state="readonly")
self.sdr_accuracy_test_btn.config(state=tk.NORMAL)
self.app.log_gui.log("✓ SDR 色准单步调试已启用")
elif test_item == "rgb":
self.sdr_rgb_combo.config(state="readonly")
self.sdr_rgb_test_btn.config(state=tk.NORMAL)
self.app.log_gui.log("✓ SDR RGB 单步调试已启用")
elif test_type == "hdr_movie":
if test_item == "eotf":
self.hdr_gray_combo.config(state="readonly")
self.hdr_eotf_test_btn.config(state=tk.NORMAL)
self.app.log_gui.log("✓ HDR EOTF 单步调试已启用")
elif test_item == "accuracy":
self.hdr_color_combo.config(state="readonly")
self.hdr_accuracy_test_btn.config(state=tk.NORMAL)
self.app.log_gui.log("✓ HDR 色准单步调试已启用")
elif test_item == "rgb":
self.hdr_rgb_combo.config(state="readonly")
self.hdr_rgb_test_btn.config(state=tk.NORMAL)
self.app.log_gui.log("✓ HDR RGB 单步调试已启用")
def disable_all_debug(self):
"""禁用所有单步调试(新测试开始时调用)"""
self.test_completed = False
self.original_data.clear()
# 禁用屏模组
self.screen_gray_combo.config(state="disabled")
self.screen_test_btn.config(state=tk.DISABLED)
self.screen_result_tree.delete(*self.screen_result_tree.get_children())
self.screen_rgb_combo.config(state="disabled")
self.screen_rgb_test_btn.config(state=tk.DISABLED)
self.screen_rgb_result_tree.delete(*self.screen_rgb_result_tree.get_children())
# 禁用 SDR
self.sdr_gray_combo.config(state="disabled")
self.sdr_gamma_test_btn.config(state=tk.DISABLED)
self.sdr_gamma_result_tree.delete(*self.sdr_gamma_result_tree.get_children())
self.sdr_color_combo.config(state="disabled")
self.sdr_accuracy_test_btn.config(state=tk.DISABLED)
self.sdr_accuracy_result_tree.delete(
*self.sdr_accuracy_result_tree.get_children()
)
self.sdr_rgb_combo.config(state="disabled")
self.sdr_rgb_test_btn.config(state=tk.DISABLED)
self.sdr_rgb_result_tree.delete(*self.sdr_rgb_result_tree.get_children())
# 禁用 HDR
self.hdr_gray_combo.config(state="disabled")
self.hdr_eotf_test_btn.config(state=tk.DISABLED)
self.hdr_eotf_result_tree.delete(*self.hdr_eotf_result_tree.get_children())
self.hdr_color_combo.config(state="disabled")
self.hdr_accuracy_test_btn.config(state=tk.DISABLED)
self.hdr_accuracy_result_tree.delete(
*self.hdr_accuracy_result_tree.get_children()
)
self.hdr_rgb_combo.config(state="disabled")
self.hdr_rgb_test_btn.config(state=tk.DISABLED)
self.hdr_rgb_result_tree.delete(*self.hdr_rgb_result_tree.get_children())
self.hide_all_panels()
# ==================== 单步测试执行 ====================
def run_single_step(self, test_type, test_item):
"""
执行单步测试
Args:
test_type: screen_module / sdr_movie / hdr_movie
test_item: gamma / eotf / accuracy / rgb
"""
# 检查设备连接
if not self.app.ca or not self.app.ucd:
messagebox.showerror("错误", "请先连接设备")
return
# 获取选择的项目
if test_item in ["gamma", "eotf"]:
if test_type == "screen_module":
selected = self.screen_gray_var.get()
elif test_type == "sdr_movie":
selected = self.sdr_gray_var.get()
elif test_type == "hdr_movie":
selected = self.hdr_gray_var.get()
elif test_item == "accuracy":
if test_type == "sdr_movie":
selected = self.sdr_color_var.get()
elif test_type == "hdr_movie":
selected = self.hdr_color_var.get()
elif test_item == "rgb":
if test_type == "screen_module":
selected = self.screen_rgb_var.get()
elif test_type == "sdr_movie":
selected = self.sdr_rgb_var.get()
elif test_type == "hdr_movie":
selected = self.hdr_rgb_var.get()
# 在新线程中执行测试
thread = threading.Thread(
target=self._run_single_step_thread,
args=(test_type, test_item, selected),
daemon=True,
)
thread.start()
def _run_single_step_thread(self, test_type, test_item, selected):
"""单步测试线程"""
try:
self.app.log_gui.log("=" * 50)
self.app.log_gui.log(
f"开始单步调试: {test_type} - {test_item} - {selected}"
)
self.app.log_gui.log("=" * 50)
# 禁用按钮
self._disable_test_button(test_type, test_item)
# 根据测试类型设置信号格式
self._setup_signal_format(test_type)
# 获取图案索引并发送
if test_item in ["gamma", "eotf"]:
pattern_index = self.get_gray_index(selected)
self.app.config.set_current_pattern("gray")
elif test_item == "accuracy":
pattern_index = self.get_color_index(selected)
self.app.config.set_current_pattern("accuracy")
elif test_item == "rgb":
pattern_index = self.get_rgb_index(selected)
self.app.config.set_current_pattern("rgb")
# 设置图案
self.app.ucd.set_ucd_params(self.app.config)
# 跳转到目标图案
for i in range(pattern_index + 1):
self.app.ucd.set_next_pattern()
self.app.ucd.run()
time.sleep(1.5)
# 测量数据
x, y, lv, X, Y, Z = self.app.ca.readAllDisplay()
self.app.log_gui.log(
f"✓ 测量完成: x={x:.4f}, y={y:.4f}, lv={lv:.2f}, "
f"X={X:.4f}, Y={Y:.4f}, Z={Z:.4f}"
)
# 对比数据
self._compare_and_display(
test_type, test_item, selected, [x, y, lv, X, Y, Z]
)
# 重新启用按钮
self._enable_test_button(test_type, test_item)
except Exception as e:
self.app.log_gui.log(f"❌ 单步测试失败: {str(e)}")
import traceback
self.app.log_gui.log(traceback.format_exc())
self._enable_test_button(test_type, test_item)
def _setup_signal_format(self, test_type):
"""设置信号格式"""
if test_type == "screen_module":
self.app.ucd.set_ucd_params(self.app.config)
elif test_type == "sdr_movie":
self.app.ucd.set_sdr_format(
color_space=self.app.sdr_color_space_var.get(),
gamma=self.app.sdr_gamma_type_var.get(),
data_range=self.app.sdr_data_range_var.get(),
bit_depth=self.app.sdr_bit_depth_var.get(),
)
elif test_type == "hdr_movie":
self.app.ucd.set_hdr_format(
color_space=self.app.hdr_color_space_var.get(),
data_range=self.app.hdr_data_range_var.get(),
bit_depth=self.app.hdr_bit_depth_var.get(),
max_cll=self.app.hdr_maxcll_var.get(),
max_fall=self.app.hdr_maxfall_var.get(),
)
def _compare_and_display(self, test_type, test_item, selected, new_data):
"""对比数据并显示"""
# 获取原始数据
key = f"{test_type}_{test_item}"
if key not in self.original_data:
self.app.log_gui.log("⚠️ 未找到原始测试数据")
return
original_data_list = self.original_data[key]
# 找到对应的原始数据
if test_item in ["gamma", "eotf"]:
index = self.get_gray_index(selected)
elif test_item == "accuracy":
index = self.get_color_index(selected)
elif test_item == "rgb":
index = self.get_rgb_index(selected)
if index >= len(original_data_list):
self.app.log_gui.log(f"⚠️ 索引超出范围: {index}")
return
original_data = original_data_list[index]
# ==================== ✅ 构建对比数据 ====================
comparison = {}
if test_item == "gamma":
# ========== Gamma 测试:只对比 x, y, lv ==========
comparison["x"] = (
original_data[0],
new_data[0],
new_data[0] - original_data[0],
)
comparison["y"] = (
original_data[1],
new_data[1],
new_data[1] - original_data[1],
)
comparison["lv"] = (
original_data[2],
new_data[2],
new_data[2] - original_data[2],
)
elif test_item == "eotf":
# ========== EOTF 测试:只对比 x, y, lv ==========
comparison["x"] = (
original_data[0],
new_data[0],
new_data[0] - original_data[0],
)
comparison["y"] = (
original_data[1],
new_data[1],
new_data[1] - original_data[1],
)
comparison["lv"] = (
original_data[2],
new_data[2],
new_data[2] - original_data[2],
)
elif test_item == "accuracy":
# ========== 色准测试:添加 ΔE 2000 值 ==========
# 从原始测试结果中读取 ΔE 值
original_delta_e = self._get_delta_e_from_results(test_type, selected)
# 重新计算单步测试的 ΔE 值
new_delta_e = self._calculate_delta_e_for_color(
selected, new_data[0], new_data[1], new_data[2]
)
# ΔE 值放在最上面
comparison["ΔE 2000"] = (
original_delta_e,
new_delta_e,
new_delta_e - original_delta_e,
)
# 只保留 x, y, lv
comparison["x"] = (
original_data[0],
new_data[0],
new_data[0] - original_data[0],
)
comparison["y"] = (
original_data[1],
new_data[1],
new_data[1] - original_data[1],
)
comparison["lv"] = (
original_data[2],
new_data[2],
new_data[2] - original_data[2],
)
elif test_item == "rgb":
# ========== RGB 测试:对比 x, y, lv ==========
comparison["x"] = (
original_data[0],
new_data[0],
new_data[0] - original_data[0],
)
comparison["y"] = (
original_data[1],
new_data[1],
new_data[1] - original_data[1],
)
comparison["lv"] = (
original_data[2],
new_data[2],
new_data[2] - original_data[2],
)
# 显示到对应的 Treeview
self._display_comparison(test_type, test_item, selected, comparison)
def _display_comparison(self, test_type, test_item, selected, comparison):
"""显示对比结果到 Treeview"""
# 获取对应的 Treeview
if test_type == "screen_module":
if test_item == "gamma":
tree = self.screen_result_tree
elif test_item == "rgb":
tree = self.screen_rgb_result_tree
elif test_type == "sdr_movie":
if test_item == "gamma":
tree = self.sdr_gamma_result_tree
elif test_item == "accuracy":
tree = self.sdr_accuracy_result_tree
elif test_item == "rgb":
tree = self.sdr_rgb_result_tree
elif test_type == "hdr_movie":
if test_item == "eotf":
tree = self.hdr_eotf_result_tree
elif test_item == "accuracy":
tree = self.hdr_accuracy_result_tree
elif test_item == "rgb":
tree = self.hdr_rgb_result_tree
# 清空旧数据
tree.delete(*tree.get_children())
# 插入标题行
tree.insert(
"",
"end",
values=(f"{selected}", "", "", ""),
tags=("header",),
)
# 插入对比数据
for key, (original, new, diff) in comparison.items():
# 根据参数类型设置格式和阈值
if key == "ΔE 2000":
# ΔE 使用 2 位小数
original_str = f"{original:.2f}"
new_str = f"{new:.2f}"
diff_str = f"{diff:+.2f}"
threshold = 0.5
elif key == "lv":
# 亮度使用 2 位小数
original_str = f"{original:.2f}"
new_str = f"{new:.2f}"
diff_str = f"{diff:+.2f}"
threshold = 0.5
else: # x, y
# x, y 使用 4 位小数
original_str = f"{original:.4f}"
new_str = f"{new:.4f}"
diff_str = f"{diff:+.4f}"
threshold = 0.001
# 判断差异
if abs(diff) > threshold:
tag = "warning"
else:
tag = "normal"
# ΔE 使用特殊标签
if key == "ΔE 2000":
tag = "highlight" if tag == "normal" else "highlight_warning"
tree.insert(
"",
"end",
values=(key, original_str, new_str, diff_str),
tags=(tag,),
)
# 设置标签样式
tree.tag_configure("header", background="#E3F2FD", font=("SimHei", 9, "bold"))
tree.tag_configure("normal", foreground="black")
tree.tag_configure("warning", foreground="red")
tree.tag_configure("highlight", foreground="blue", font=("SimHei", 9, "bold"))
tree.tag_configure(
"highlight_warning", foreground="red", font=("SimHei", 9, "bold")
)
def _disable_test_button(self, test_type, test_item):
"""禁用测试按钮"""
if test_type == "screen_module":
if test_item == "gamma":
self.screen_test_btn.config(state=tk.DISABLED)
elif test_item == "rgb":
self.screen_rgb_test_btn.config(state=tk.DISABLED)
elif test_type == "sdr_movie":
if test_item == "gamma":
self.sdr_gamma_test_btn.config(state=tk.DISABLED)
elif test_item == "accuracy":
self.sdr_accuracy_test_btn.config(state=tk.DISABLED)
elif test_item == "rgb":
self.sdr_rgb_test_btn.config(state=tk.DISABLED)
elif test_type == "hdr_movie":
if test_item == "eotf":
self.hdr_eotf_test_btn.config(state=tk.DISABLED)
elif test_item == "accuracy":
self.hdr_accuracy_test_btn.config(state=tk.DISABLED)
elif test_item == "rgb":
self.hdr_rgb_test_btn.config(state=tk.DISABLED)
def _enable_test_button(self, test_type, test_item):
"""启用测试按钮"""
if test_type == "screen_module":
if test_item == "gamma":
self.app.root.after(0, lambda: self.screen_test_btn.config(state=tk.NORMAL))
elif test_item == "rgb":
self.app.root.after(0, lambda: self.screen_rgb_test_btn.config(state=tk.NORMAL))
elif test_type == "sdr_movie":
if test_item == "gamma":
self.app.root.after(
0, lambda: self.sdr_gamma_test_btn.config(state=tk.NORMAL)
)
elif test_item == "accuracy":
self.app.root.after(
0, lambda: self.sdr_accuracy_test_btn.config(state=tk.NORMAL)
)
elif test_item == "rgb":
self.app.root.after(
0, lambda: self.sdr_rgb_test_btn.config(state=tk.NORMAL)
)
elif test_type == "hdr_movie":
if test_item == "eotf":
self.app.root.after(
0, lambda: self.hdr_eotf_test_btn.config(state=tk.NORMAL)
)
elif test_item == "accuracy":
self.app.root.after(
0, lambda: self.hdr_accuracy_test_btn.config(state=tk.NORMAL)
)
elif test_item == "rgb":
self.app.root.after(
0, lambda: self.hdr_rgb_test_btn.config(state=tk.NORMAL)
)
# ==================== 辅助方法 ====================
def get_gray_index(self, gray_str):
"""获取灰阶索引"""
gray_levels = [100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0]
gray_value = int(gray_str.replace("%", ""))
return gray_levels.index(gray_value)
def get_color_index(self, color_name):
"""获取色块索引"""
color_names = self.get_29_color_names()
return color_names.index(color_name)
def get_rgb_index(self, color_name):
"""获取RGB颜色索引"""
rgb_colors = ["Red", "Green", "Blue"]
return rgb_colors.index(color_name)
def get_29_color_names(self):
"""获取29色名称列表"""
return [
"White",
"Gray 80",
"Gray 65",
"Gray 50",
"Gray 35",
"Dark Skin",
"Light Skin",
"Blue Sky",
"Foliage",
"Blue Flower",
"Bluish Green",
"Orange",
"Purplish Blue",
"Moderate Red",
"Purple",
"Yellow Green",
"Orange Yellow",
"Blue (Legacy)",
"Green (Legacy)",
"Red (Legacy)",
"Yellow (Legacy)",
"Magenta (Legacy)",
"Cyan (Legacy)",
"100% Red",
"100% Green",
"100% Blue",
"100% Cyan",
"100% Magenta",
"100% Yellow",
]
def _get_delta_e_from_results(self, test_type, color_name):
"""从原始测试结果中读取 ΔE 值"""
try:
self.app.log_gui.log(f"[读取 ΔE] 开始:")
self.app.log_gui.log(f" test_type = {test_type}")
self.app.log_gui.log(f" color_name = {color_name}")
# ✅ 正确的访问方式:通过 test_items
if "accuracy" not in self.app.results.test_items:
self.app.log_gui.log(" ✗ 未找到 accuracy 测试项")
return 0.0
test_item = self.app.results.test_items["accuracy"]
accuracy_result = test_item.final_result
self.app.log_gui.log(f" accuracy_result = {accuracy_result is not None}")
if not accuracy_result:
self.app.log_gui.log(" ✗ accuracy_result 为空")
return 0.0
# 获取色块名称列表和 ΔE 值列表
color_patches = accuracy_result.get("color_patches", [])
delta_e_values = accuracy_result.get("delta_e_values", [])
self.app.log_gui.log(f" color_patches 数量: {len(color_patches)}")
self.app.log_gui.log(f" delta_e_values 数量: {len(delta_e_values)}")
if color_patches:
self.app.log_gui.log(f" 前3个色块: {color_patches[:3]}")
if delta_e_values:
self.app.log_gui.log(f" 前3个ΔE: {delta_e_values[:3]}")
# 查找对应色块的索引
try:
index = color_patches.index(color_name)
delta_e = delta_e_values[index]
self.app.log_gui.log(
f" ✓ 找到 {color_name}: index={index}, ΔE={delta_e:.2f}"
)
return delta_e
except ValueError:
self.app.log_gui.log(f" ✗ 未找到色块 '{color_name}'")
self.app.log_gui.log(f" 可用色块: {color_patches}")
return 0.0
except IndexError:
self.app.log_gui.log(f" ✗ 索引超出范围: {index}/{len(delta_e_values)}")
return 0.0
except Exception as e:
self.app.log_gui.log(f"⚠️ 读取 ΔE 失败: {str(e)}")
import traceback
self.app.log_gui.log(traceback.format_exc())
return 0.0
def _calculate_delta_e_for_color(
self, color_name, measured_x, measured_y, measured_lv
):
"""计算单个色块的 ΔE 2000"""
try:
# 获取标准 xy 坐标
test_type = self.current_test_type
standards = self.app.get_accuracy_color_standards(test_type)
if color_name not in standards:
return 0.0
standard_x, standard_y = standards[color_name]
# 调用主程序的 ΔE 计算方法
delta_e = self.app.calculate_delta_e_2000(
measured_x, measured_y, measured_lv, standard_x, standard_y
)
return delta_e
except Exception as e:
self.app.log_gui.log(f"⚠️ 计算 ΔE 失败: {str(e)}")
return 0.0