修改摸底测试功能、修改pattern控制逻辑

This commit is contained in:
xinzhu.yin
2026-05-13 17:17:13 +08:00
parent 9a52e34f2b
commit 0513f810bd
13 changed files with 479 additions and 3067 deletions

View File

@@ -435,14 +435,14 @@ def create_test_type_frame(self):
)
self.ai_image_btn.pack(fill=tk.X, padx=0, pady=1)
self.single_step_btn = ttk.Button(
self.sidebar_frame,
text="单步调试",
style="Sidebar.TButton",
command=self.toggle_single_step_panel,
takefocus=False,
)
self.single_step_btn.pack(fill=tk.X, padx=0, pady=1)
# self.single_step_btn = ttk.Button(
# self.sidebar_frame,
# text="单步调试",
# style="Sidebar.TButton",
# command=self.toggle_single_step_panel,
# takefocus=False,
# )
# self.single_step_btn.pack(fill=tk.X, padx=0, pady=1)
self.pantone_baseline_btn = ttk.Button(
self.sidebar_frame,

View File

@@ -2,23 +2,16 @@
from __future__ import annotations
import csv
import datetime
import os
import tempfile
import threading
import tkinter as tk
from tkinter import filedialog, messagebox
import ttkbootstrap as ttk
from PIL import Image
from drivers.ucd_helpers import get_current_resolution, send_image_pattern
_PATTERN_FILE = "pantone_patterns_2670.csv"
_TEMPLATE_FILE = "pantone\xa02670\xa0colors.xlsx"
_TARGET_RESULT_COUNT = 2670
def create_pantone_baseline_panel(self):
@@ -34,6 +27,7 @@ def create_pantone_baseline_panel(self):
self._pantone_pause_requested = False
self._pantone_stop_requested = False
self._pantone_next_index = 0
self._pantone_target_count = 0
root = ttk.Frame(frame, padding=10)
root.pack(fill=tk.BOTH, expand=True)
@@ -47,12 +41,12 @@ def create_pantone_baseline_panel(self):
).pack(side=tk.LEFT)
self.pantone_status_var = tk.StringVar(value="未开始")
self.pantone_progress_var = tk.StringVar(value="0 / 2670")
self.pantone_progress_var = tk.StringVar(value="0 / 0")
self.pantone_settle_var = tk.StringVar(value="0.35")
config_row = ttk.LabelFrame(root, text="任务配置", padding=8)
config_row.pack(fill=tk.X)
ttk.Label(config_row, text=f"Pattern来源: settings/{_PATTERN_FILE}").pack(
ttk.Label(config_row, text=f"Pattern来源: settings/{_TEMPLATE_FILE}").pack(
side=tk.LEFT
)
ttk.Label(config_row, text="稳定等待(s):").pack(side=tk.LEFT, padx=(14, 4))
@@ -160,38 +154,38 @@ def toggle_pantone_baseline_panel(self):
def _load_patterns(self):
path = os.path.join("settings", _PATTERN_FILE)
path = os.path.join("settings", _TEMPLATE_FILE)
if not os.path.isfile(path):
raise FileNotFoundError(f"未找到 pattern 文件: {path}")
raise FileNotFoundError(f"未找到模板文件: {path}")
from openpyxl import load_workbook
patterns = []
with open(path, "r", encoding="utf-8-sig", newline="") as fp:
reader = csv.DictReader(fp)
for row in reader:
wb = load_workbook(path, read_only=True, data_only=True)
ws = wb.active
try:
for row in ws.iter_rows(min_row=2, values_only=True):
if not row:
continue
try:
r = int(row.get("R", "").strip())
g = int(row.get("G", "").strip())
b = int(row.get("B", "").strip())
r = int(row[0]) if row[0] is not None else None
g = int(row[1]) if len(row) > 1 and row[1] is not None else None
b = int(row[2]) if len(row) > 2 and row[2] is not None else None
except Exception:
continue
if r is None or g is None or b is None:
continue
if min(r, g, b) < 0 or max(r, g, b) > 255:
continue
patterns.append((r, g, b))
finally:
wb.close()
if not patterns:
raise RuntimeError("pattern 文件为空或格式不正确,需包含 R,G,B")
raise RuntimeError("模板中未找到有效 RGB 列表(需包含 R/G/B 三列)")
return patterns
def _build_temp_patch(self, rgb):
width, height = get_current_resolution(self.ucd)
temp_dir = os.path.join(tempfile.gettempdir(), "pq_pantone_baseline")
os.makedirs(temp_dir, exist_ok=True)
file_path = os.path.join(temp_dir, "pantone_current_patch.png")
Image.new("RGB", (width, height), rgb).save(file_path, format="PNG")
return file_path
def _start_pantone_baseline(self):
if self._pantone_running:
messagebox.showinfo("提示", "Pantone 任务正在执行")
@@ -213,6 +207,7 @@ def _start_pantone_baseline(self):
try:
self.pantone_patterns = _load_patterns(self)
self._pantone_target_count = len(self.pantone_patterns)
except Exception as exc:
messagebox.showerror("读取失败", str(exc))
return
@@ -228,7 +223,7 @@ def _start_pantone_baseline(self):
self._pantone_control_event = threading.Event()
self._pantone_next_index = 0
self.pantone_status_var.set("执行中")
self.pantone_progress_var.set(f"0 / {_TARGET_RESULT_COUNT}")
self.pantone_progress_var.set(f"0 / {self._pantone_target_count}")
self.pantone_results = []
for item in self.pantone_tree.get_children():
self.pantone_tree.delete(item)
@@ -244,9 +239,6 @@ def _resume_pantone_baseline(self):
if not self._pantone_paused:
messagebox.showinfo("提示", "当前没有可继续的暂停任务")
return
if self._pantone_next_index >= _TARGET_RESULT_COUNT:
messagebox.showinfo("提示", "任务已完成,无需继续")
return
if not getattr(self, "ucd", None) or not self.ucd.status:
messagebox.showwarning("警告", "请先连接 UCD323")
return
@@ -264,10 +256,15 @@ def _resume_pantone_baseline(self):
try:
self.pantone_patterns = _load_patterns(self)
self._pantone_target_count = len(self.pantone_patterns)
except Exception as exc:
messagebox.showerror("读取失败", str(exc))
return
if self._pantone_next_index >= self._pantone_target_count:
messagebox.showinfo("提示", "任务已完成,无需继续")
return
self._pantone_running = True
self._pantone_paused = False
self._pantone_pause_requested = False
@@ -280,13 +277,14 @@ def _resume_pantone_baseline(self):
def _launch_worker(self, start_index, settle):
total = _TARGET_RESULT_COUNT
total = self._pantone_target_count or len(self.pantone_patterns)
def worker():
end_state = "completed"
try:
src = self.pantone_patterns
src_count = len(src)
rgb_session = self.pattern_service.prepare_session("rgb", log_details=False)
self._dispatch_ui(
self.log_gui.log,
f"Pantone 认证摸底启动: source={src_count}, target={total}, start={start_index + 1}",
@@ -301,9 +299,10 @@ def _launch_worker(self, start_index, settle):
break
r, g, b = src[i % src_count]
image_path = _build_temp_patch(self, (r, g, b))
if not send_image_pattern(self.ucd, image_path):
raise RuntimeError(f"{i + 1} 组发送失败")
try:
self.pattern_service.send_rgb((r, g, b), session=rgb_session)
except Exception as exc:
raise RuntimeError(f"{i + 1} 组发送失败: {exc}") from exc
if settle > 0 and self._pantone_control_event is not None:
self._pantone_control_event.clear()
@@ -360,6 +359,19 @@ def _launch_worker(self, start_index, settle):
f"Pantone 任务完成,共 {len(self.pantone_results)} 条数据",
"success",
)
try:
auto_path = _auto_save_template(self)
self._dispatch_ui(
self.log_gui.log,
f"Pantone 模板已自动保存: {auto_path}",
"success",
)
except Exception as exc:
self._dispatch_ui(
self.log_gui.log,
f"Pantone 自动保存模板失败: {exc}",
"error",
)
except Exception as exc:
self._pantone_paused = False
self._dispatch_ui(self.pantone_status_var.set, "执行失败")
@@ -430,7 +442,8 @@ def _clear_results(self):
self._pantone_next_index = 0
for item in self.pantone_tree.get_children():
self.pantone_tree.delete(item)
self.pantone_progress_var.set(f"0 / {_TARGET_RESULT_COUNT}")
self._pantone_target_count = 0
self.pantone_progress_var.set("0 / 0")
self.pantone_status_var.set("结果已清空")
_set_button_states(self)
@@ -447,7 +460,7 @@ def _set_button_states(self):
self.pantone_pause_btn.configure(state=tk.DISABLED)
self.pantone_end_btn.configure(state=tk.NORMAL if (self._pantone_paused or self.pantone_results) else tk.DISABLED)
can_resume = self._pantone_paused and self._pantone_next_index < _TARGET_RESULT_COUNT
can_resume = self._pantone_paused and self._pantone_next_index < self._pantone_target_count
self.pantone_resume_btn.configure(state=tk.NORMAL if can_resume else tk.DISABLED)
@@ -456,7 +469,7 @@ def _save_as_template(self):
messagebox.showinfo("提示", "暂无可导出的结果")
return
default_name = "pantone 2670 colors.xlsx"
default_name = _TEMPLATE_FILE.replace("\xa0", " ")
path = filedialog.asksaveasfilename(
title="另存为 Pantone 模板",
defaultextension=".xlsx",
@@ -466,41 +479,69 @@ def _save_as_template(self):
if not path:
return
# 优先复制 settings 模板,再覆盖数据区;没有模板时自动创建同结构表。
template_path = os.path.join("settings", _TEMPLATE_FILE)
try:
from openpyxl import load_workbook, Workbook
if os.path.isfile(template_path):
wb = load_workbook(template_path)
ws = wb.active
else:
wb = Workbook()
ws = wb.active
ws.title = "Sheet1"
ws.cell(row=1, column=1, value="R")
ws.cell(row=1, column=2, value="G")
ws.cell(row=1, column=3, value="B")
ws.cell(row=1, column=4, value="L")
ws.cell(row=1, column=5, value="x")
ws.cell(row=1, column=6, value="y")
# 清空旧数据
max_row = max(ws.max_row, 2)
for row in range(2, max_row + 1):
for col in range(1, 7):
ws.cell(row=row, column=col, value=None)
for idx, item in enumerate(self.pantone_results, start=2):
ws.cell(row=idx, column=1, value=int(item["r"]))
ws.cell(row=idx, column=2, value=int(item["g"]))
ws.cell(row=idx, column=3, value=int(item["b"]))
ws.cell(row=idx, column=4, value=float(item["l"]))
ws.cell(row=idx, column=5, value=float(item["x"]))
ws.cell(row=idx, column=6, value=float(item["y"]))
wb.save(path)
_write_template_xlsx(self, path)
self.log_gui.log(f"Pantone 模板已保存: {path}", level="success")
self.pantone_status_var.set(f"已保存: {os.path.basename(path)}")
except Exception as exc:
messagebox.showerror("保存失败", f"写入 xlsx 失败: {exc}")
def _resolve_results_dir(self):
if getattr(self, "config_file", None):
root_dir = os.path.dirname(os.path.dirname(self.config_file))
else:
root_dir = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
)
results_dir = os.path.join(root_dir, "results")
os.makedirs(results_dir, exist_ok=True)
return results_dir
def _auto_save_template(self):
results_dir = _resolve_results_dir(self)
target_count = len(self.pantone_results)
filename = (
f"pantone_{target_count}_baseline_"
f"{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
)
path = os.path.join(results_dir, filename)
_write_template_xlsx(self, path)
return path
def _write_template_xlsx(self, path):
# 优先复制 settings 模板,再覆盖数据区;没有模板时自动创建同结构表。
template_path = os.path.join("settings", _TEMPLATE_FILE)
from openpyxl import load_workbook, Workbook
if os.path.isfile(template_path):
wb = load_workbook(template_path)
ws = wb.active
else:
wb = Workbook()
ws = wb.active
ws.title = "Sheet1"
ws.cell(row=1, column=1, value="R")
ws.cell(row=1, column=2, value="G")
ws.cell(row=1, column=3, value="B")
ws.cell(row=1, column=4, value="L")
ws.cell(row=1, column=5, value="x")
ws.cell(row=1, column=6, value="y")
# 清空旧数据
max_row = max(ws.max_row, 2)
for row in range(2, max_row + 1):
for col in range(1, 7):
ws.cell(row=row, column=col, value=None)
for idx, item in enumerate(self.pantone_results, start=2):
ws.cell(row=idx, column=1, value=int(item["r"]))
ws.cell(row=idx, column=2, value=int(item["g"]))
ws.cell(row=idx, column=3, value=int(item["b"]))
ws.cell(row=idx, column=4, value=float(item["l"]))
ws.cell(row=idx, column=5, value=float(item["x"]))
ws.cell(row=idx, column=6, value=float(item["y"]))
wb.save(path)