修改深色模式下结果图片显示异常
This commit is contained in:
@@ -25,6 +25,7 @@ from typing import TYPE_CHECKING
|
|||||||
from app.ucd_domain import ConnectionChanged, UcdError
|
from app.ucd_domain import ConnectionChanged, UcdError
|
||||||
from drivers.caSerail import CASerail
|
from drivers.caSerail import CASerail
|
||||||
from drivers.ucd_driver import DeviceInfo
|
from drivers.ucd_driver import DeviceInfo
|
||||||
|
from app.views.modern_styles import get_theme_palette
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
@@ -189,8 +190,7 @@ class ConnectionController:
|
|||||||
self.disconnect_ucd()
|
self.disconnect_ucd()
|
||||||
self.disconnect_ca()
|
self.disconnect_ca()
|
||||||
self._enable_widgets()
|
self._enable_widgets()
|
||||||
self._app.ucd_status_indicator.config(bg="gray")
|
self._app.refresh_connection_indicators()
|
||||||
self._app.ca_status_indicator.config(bg="gray")
|
|
||||||
self._app.status_var.set("串口连接已断开")
|
self._app.status_var.set("串口连接已断开")
|
||||||
except Exception as exc: # noqa: BLE001
|
except Exception as exc: # noqa: BLE001
|
||||||
self._log(f"断开连接时发生错误: {exc}", level="info")
|
self._log(f"断开连接时发生错误: {exc}", level="info")
|
||||||
@@ -212,10 +212,7 @@ class ConnectionController:
|
|||||||
)
|
)
|
||||||
app.ca_com_combo.config(values=com_ports)
|
app.ca_com_combo.config(values=com_ports)
|
||||||
|
|
||||||
if hasattr(app, "ucd_status_indicator"):
|
app.refresh_connection_indicators()
|
||||||
app.ucd_status_indicator.config(bg="gray")
|
|
||||||
if hasattr(app, "ca_status_indicator"):
|
|
||||||
app.ca_status_indicator.config(bg="gray")
|
|
||||||
|
|
||||||
app.update_config()
|
app.update_config()
|
||||||
|
|
||||||
@@ -254,7 +251,45 @@ def check_com_connections(self: "PQAutomationApp"):
|
|||||||
|
|
||||||
|
|
||||||
def update_connection_indicator(self: "PQAutomationApp", indicator, connected):
|
def update_connection_indicator(self: "PQAutomationApp", indicator, connected):
|
||||||
indicator.config(bg="green" if connected else "red")
|
_draw_connection_indicator(indicator, "green" if connected else "red")
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_connection_indicators(self: "PQAutomationApp"):
|
||||||
|
"""根据当前设备状态重画 UCD / CA 指示灯。"""
|
||||||
|
if hasattr(self, "ucd_status_indicator"):
|
||||||
|
ucd_connected = bool(getattr(self.ucd, "status", False))
|
||||||
|
_draw_connection_indicator(
|
||||||
|
self.ucd_status_indicator,
|
||||||
|
"green" if ucd_connected else "gray",
|
||||||
|
)
|
||||||
|
if hasattr(self, "ca_status_indicator"):
|
||||||
|
ca_connected = getattr(self, "ca", None) is not None
|
||||||
|
_draw_connection_indicator(
|
||||||
|
self.ca_status_indicator,
|
||||||
|
"green" if ca_connected else "gray",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _draw_connection_indicator(canvas, state: str) -> None:
|
||||||
|
palette = get_theme_palette()
|
||||||
|
color_map = {
|
||||||
|
"green": "#2ECC71",
|
||||||
|
"red": "#E74C3C",
|
||||||
|
"gray": "#9AA3AD",
|
||||||
|
}
|
||||||
|
fill = color_map.get(state, state)
|
||||||
|
border = palette["border"]
|
||||||
|
bg = palette["card_bg"]
|
||||||
|
try:
|
||||||
|
canvas.configure(bg=bg, highlightbackground=border, highlightcolor=border)
|
||||||
|
canvas.delete("all")
|
||||||
|
# 保持原有视觉:方形状态灯(红/绿/灰)
|
||||||
|
canvas.create_rectangle(0, 0, 15, 15, fill=fill, outline=border, width=1)
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
canvas.config(bg=fill)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def check_port_connection(self: "PQAutomationApp", is_ucd=True):
|
def check_port_connection(self: "PQAutomationApp", is_ucd=True):
|
||||||
@@ -323,6 +358,7 @@ __all__ = [
|
|||||||
"refresh_com_ports",
|
"refresh_com_ports",
|
||||||
"check_com_connections",
|
"check_com_connections",
|
||||||
"update_connection_indicator",
|
"update_connection_indicator",
|
||||||
|
"refresh_connection_indicators",
|
||||||
"check_port_connection",
|
"check_port_connection",
|
||||||
"enable_com_widgets",
|
"enable_com_widgets",
|
||||||
"disconnect_com_connections",
|
"disconnect_com_connections",
|
||||||
@@ -338,6 +374,7 @@ class DeviceConnectionMixin:
|
|||||||
refresh_com_ports = refresh_com_ports
|
refresh_com_ports = refresh_com_ports
|
||||||
check_com_connections = check_com_connections
|
check_com_connections = check_com_connections
|
||||||
update_connection_indicator = update_connection_indicator
|
update_connection_indicator = update_connection_indicator
|
||||||
|
refresh_connection_indicators = refresh_connection_indicators
|
||||||
check_port_connection = check_port_connection
|
check_port_connection = check_port_connection
|
||||||
enable_com_widgets = enable_com_widgets
|
enable_com_widgets = enable_com_widgets
|
||||||
disconnect_com_connections = disconnect_com_connections
|
disconnect_com_connections = disconnect_com_connections
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ from typing import TYPE_CHECKING
|
|||||||
|
|
||||||
from matplotlib.patches import Rectangle
|
from matplotlib.patches import Rectangle
|
||||||
from matplotlib.lines import Line2D
|
from matplotlib.lines import Line2D
|
||||||
from matplotlib.patches import Circle
|
import matplotlib.colors as mcolors
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from app.views.modern_styles import get_theme_palette
|
||||||
|
|
||||||
from app.plots.gamut_background import get_cie1976_background
|
from app.plots.gamut_background import get_cie1976_background
|
||||||
from app.tests.color_accuracy import get_accuracy_color_standards
|
from app.tests.color_accuracy import get_accuracy_color_standards
|
||||||
@@ -112,6 +115,9 @@ def _draw_left_panel(ax, color_patches, delta_e_values, font_scale=1.0, dark_mod
|
|||||||
spine.set_linewidth(0.9)
|
spine.set_linewidth(0.9)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# 子图:CIE 1976 u'v' 色度图(目标 vs 实测)
|
# 子图:CIE 1976 u'v' 色度图(目标 vs 实测)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
@@ -121,12 +127,14 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0,
|
|||||||
ax.clear()
|
ax.clear()
|
||||||
try:
|
try:
|
||||||
bg, bbox = get_cie1976_background()
|
bg, bbox = get_cie1976_background()
|
||||||
|
if bg.shape[-1] == 4:
|
||||||
|
bg = bg[:, :, :3]
|
||||||
xmin, xmax, ymin, ymax = bbox
|
xmin, xmax, ymin, ymax = bbox
|
||||||
ax.imshow(
|
ax.imshow(
|
||||||
bg,
|
bg,
|
||||||
extent=(xmin, xmax, ymin, ymax),
|
extent=(xmin, xmax, ymin, ymax),
|
||||||
origin="lower",
|
origin="lower",
|
||||||
interpolation="bicubic",
|
interpolation="bilinear",
|
||||||
zorder=0,
|
zorder=0,
|
||||||
aspect="auto",
|
aspect="auto",
|
||||||
)
|
)
|
||||||
@@ -181,8 +189,10 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0,
|
|||||||
s_u, s_v = _xy_to_uv(sx, sy)
|
s_u, s_v = _xy_to_uv(sx, sy)
|
||||||
|
|
||||||
# face = get_patch_color_from_xy(name, (sx, sy)).strip().upper()
|
# face = get_patch_color_from_xy(name, (sx, sy)).strip().upper()
|
||||||
face = _COLOR_MAP.get(name, "#888888")
|
face = _COLOR_MAP.get(name, "#FFFFFF")
|
||||||
print(name, face)
|
# face = get_patch_color_from_xy(name, (mx, my))
|
||||||
|
# face = "#FF0000"
|
||||||
|
|
||||||
|
|
||||||
# 目标点(Target) 空心方框
|
# 目标点(Target) 空心方框
|
||||||
ax.scatter(
|
ax.scatter(
|
||||||
@@ -300,17 +310,24 @@ def _draw_result_judgement(ax, accuracy_data, font_scale=1.0, dark_mode=False):
|
|||||||
|
|
||||||
def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
|
def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
|
||||||
"""绘制色准测试结果 - Calman 风格(色块 + CIE 1976 u'v' + 统计)。"""
|
"""绘制色准测试结果 - Calman 风格(色块 + CIE 1976 u'v' + 统计)。"""
|
||||||
|
palette = get_theme_palette()
|
||||||
fig = self.accuracy_fig
|
|
||||||
fig.clear()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from app.views.theme_manager import is_dark
|
from app.views.theme_manager import is_dark
|
||||||
dark_mode = is_dark()
|
dark_mode = is_dark()
|
||||||
except Exception:
|
except Exception:
|
||||||
dark_mode = False
|
dark_mode = False
|
||||||
|
|
||||||
fig.patch.set_facecolor("#1B1F24" if dark_mode else "#FFFFFF")
|
fig = self.accuracy_fig
|
||||||
|
fig.clear()
|
||||||
|
try:
|
||||||
|
fig.set_layout_engine(None)
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
fig.set_tight_layout(False)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
fig.patch.set_facecolor(palette["bg"])
|
||||||
|
|
||||||
# 根据当前画布像素尺寸动态缩放字体,避免窗口缩小时文字挤压重叠。
|
# 根据当前画布像素尺寸动态缩放字体,避免窗口缩小时文字挤压重叠。
|
||||||
font_scale = 1.0
|
font_scale = 1.0
|
||||||
@@ -341,13 +358,12 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
|
|||||||
else:
|
else:
|
||||||
title = f"{test_type_name} - 色准测试(全 29色 | Gamma {target_gamma})"
|
title = f"{test_type_name} - 色准测试(全 29色 | Gamma {target_gamma})"
|
||||||
|
|
||||||
title_color = "#F3F5F7" if dark_mode else "#111"
|
|
||||||
fig.suptitle(
|
fig.suptitle(
|
||||||
title,
|
title,
|
||||||
fontsize=max(8, 11 * font_scale),
|
fontsize=max(8, 11 * font_scale),
|
||||||
y=0.975,
|
y=0.975,
|
||||||
fontweight="bold",
|
fontweight="bold",
|
||||||
color=title_color,
|
color=palette["fg"],
|
||||||
)
|
)
|
||||||
|
|
||||||
gs = fig.add_gridspec(
|
gs = fig.add_gridspec(
|
||||||
@@ -362,6 +378,8 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
|
|||||||
ax_left = fig.add_subplot(gs[0, 0])
|
ax_left = fig.add_subplot(gs[0, 0])
|
||||||
ax_uv = fig.add_subplot(gs[0, 1])
|
ax_uv = fig.add_subplot(gs[0, 1])
|
||||||
ax_judge = fig.add_subplot(gs[1, :])
|
ax_judge = fig.add_subplot(gs[1, :])
|
||||||
|
for ax in (ax_left, ax_uv, ax_judge):
|
||||||
|
ax.set_facecolor(palette["card_bg"])
|
||||||
|
|
||||||
# 兼容外部对 self.accuracy_ax 的引用
|
# 兼容外部对 self.accuracy_ax 的引用
|
||||||
self.accuracy_ax = ax_judge
|
self.accuracy_ax = ax_judge
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_cct 原样搬迁。
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from app.views.modern_styles import get_theme_palette
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
@@ -11,11 +12,36 @@ if TYPE_CHECKING:
|
|||||||
from pqAutomationApp import PQAutomationApp
|
from pqAutomationApp import PQAutomationApp
|
||||||
|
|
||||||
|
|
||||||
|
def _is_dark_palette(palette: dict[str, str]) -> bool:
|
||||||
|
"""根据主题背景色亮度判断是否深色主题。"""
|
||||||
|
bg = palette.get("bg", "#FFFFFF").lstrip("#")
|
||||||
|
try:
|
||||||
|
r = int(bg[0:2], 16)
|
||||||
|
g = int(bg[2:4], 16)
|
||||||
|
b = int(bg[4:6], 16)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return (r * 299 + g * 587 + b * 114) / 1000 < 128
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def plot_cct(self: "PQAutomationApp", test_type):
|
def plot_cct(self: "PQAutomationApp", test_type):
|
||||||
"""绘制 x 和 y 坐标分离图 - 每个点标注纵坐标值"""
|
"""绘制 x 和 y 坐标分离图 - 每个点标注纵坐标值"""
|
||||||
|
palette = get_theme_palette()
|
||||||
|
dark_mode = _is_dark_palette(palette)
|
||||||
|
x_line_color = "#2F8BFF" if dark_mode else "#0A4BFF"
|
||||||
|
y_line_color = "#FF4D4D" if dark_mode else "#D90429"
|
||||||
|
ideal_line_color = "#00C853" if dark_mode else "#198754"
|
||||||
|
x_tol_color = "#FF7070" if dark_mode else "#C0392B"
|
||||||
|
y_tol_color = "#FFB74D" if dark_mode else "#D68910"
|
||||||
|
grid_color = "#566070" if dark_mode else "#B8BDC3"
|
||||||
|
axis_text = "#EDF2FA" if dark_mode else palette["fg"]
|
||||||
|
axis_sub_text = "#C8D2E0" if dark_mode else "#222222"
|
||||||
|
legend_bg = "#131821" if dark_mode else "#FFFFFF"
|
||||||
|
legend_edge = "#A4B2C6" if dark_mode else palette["border"]
|
||||||
|
|
||||||
self.cct_fig.clear()
|
self.cct_fig.clear()
|
||||||
|
self.cct_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
|
||||||
gray_data = self.results.get_intermediate_data("shared", "gray")
|
gray_data = self.results.get_intermediate_data("shared", "gray")
|
||||||
if not gray_data:
|
if not gray_data:
|
||||||
@@ -31,7 +57,7 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="center",
|
va="center",
|
||||||
fontsize=14,
|
fontsize=14,
|
||||||
color="red",
|
color=palette["danger"],
|
||||||
)
|
)
|
||||||
ax.axis("off")
|
ax.axis("off")
|
||||||
self.cct_canvas.draw()
|
self.cct_canvas.draw()
|
||||||
@@ -111,12 +137,20 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
# 为所有测试类型创建子图
|
# 为所有测试类型创建子图
|
||||||
ax1 = self.cct_fig.add_subplot(211)
|
ax1 = self.cct_fig.add_subplot(211)
|
||||||
ax2 = self.cct_fig.add_subplot(212)
|
ax2 = self.cct_fig.add_subplot(212)
|
||||||
|
for ax in (ax1, ax2):
|
||||||
|
ax.set_facecolor(palette["card_bg"])
|
||||||
|
for spine in ax.spines.values():
|
||||||
|
spine.set_color(palette["border"])
|
||||||
|
ax.tick_params(labelsize=8, colors=axis_sub_text)
|
||||||
|
ax.xaxis.label.set_color(axis_text)
|
||||||
|
ax.yaxis.label.set_color(axis_text)
|
||||||
|
|
||||||
# ========== 上图:x coordinates ==========
|
# ========== 上图:x coordinates ==========
|
||||||
ax1.plot(
|
ax1.plot(
|
||||||
grayscale,
|
grayscale,
|
||||||
x_measured,
|
x_measured,
|
||||||
"b-o",
|
color=x_line_color,
|
||||||
|
marker="o",
|
||||||
label="屏本体",
|
label="屏本体",
|
||||||
linewidth=2,
|
linewidth=2,
|
||||||
markersize=4,
|
markersize=4,
|
||||||
@@ -133,13 +167,13 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="bottom",
|
va="bottom",
|
||||||
fontsize=7,
|
fontsize=7,
|
||||||
color="blue",
|
color=x_line_color,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=0.2",
|
boxstyle="round,pad=0.2",
|
||||||
facecolor="white",
|
facecolor=palette["card_bg"],
|
||||||
edgecolor="blue",
|
edgecolor=x_line_color,
|
||||||
alpha=0.8,
|
alpha=0.92 if dark_mode else 0.85,
|
||||||
linewidth=0.5,
|
linewidth=0.8,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -147,7 +181,7 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
full_grayscale = np.linspace(0, 100, 100)
|
full_grayscale = np.linspace(0, 100, 100)
|
||||||
ax1.axhline(
|
ax1.axhline(
|
||||||
y=x_ideal,
|
y=x_ideal,
|
||||||
color="green",
|
color=ideal_line_color,
|
||||||
linestyle="--",
|
linestyle="--",
|
||||||
linewidth=1.5,
|
linewidth=1.5,
|
||||||
label=f"x-ideal ({x_ideal:.4f})",
|
label=f"x-ideal ({x_ideal:.4f})",
|
||||||
@@ -155,30 +189,34 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
)
|
)
|
||||||
ax1.axhline(
|
ax1.axhline(
|
||||||
y=x_low,
|
y=x_low,
|
||||||
color="red",
|
color=x_tol_color,
|
||||||
linestyle=":",
|
linestyle=":",
|
||||||
linewidth=1,
|
linewidth=1,
|
||||||
alpha=0.7,
|
alpha=0.95 if dark_mode else 0.7,
|
||||||
label=f"x-low ({x_low:.4f})",
|
label=f"x-low ({x_low:.4f})",
|
||||||
zorder=2,
|
zorder=2,
|
||||||
)
|
)
|
||||||
ax1.axhline(
|
ax1.axhline(
|
||||||
y=x_high,
|
y=x_high,
|
||||||
color="red",
|
color=x_tol_color,
|
||||||
linestyle=":",
|
linestyle=":",
|
||||||
linewidth=1,
|
linewidth=1,
|
||||||
alpha=0.7,
|
alpha=0.95 if dark_mode else 0.7,
|
||||||
label=f"x-high ({x_high:.4f})",
|
label=f"x-high ({x_high:.4f})",
|
||||||
zorder=2,
|
zorder=2,
|
||||||
)
|
)
|
||||||
ax1.fill_between(
|
ax1.fill_between(
|
||||||
full_grayscale, x_low, x_high, alpha=0.15, color="blue", zorder=1
|
full_grayscale,
|
||||||
|
x_low,
|
||||||
|
x_high,
|
||||||
|
alpha=0.22 if dark_mode else 0.15,
|
||||||
|
color=x_line_color,
|
||||||
|
zorder=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
ax1.set_xlabel("灰阶 (%)", fontsize=9)
|
ax1.set_xlabel("灰阶 (%)", fontsize=9, color=axis_text)
|
||||||
ax1.set_ylabel("CIE x", fontsize=9)
|
ax1.set_ylabel("CIE x", fontsize=9, color=axis_text)
|
||||||
ax1.grid(True, linestyle="--", alpha=0.3)
|
ax1.grid(True, linestyle="--", alpha=0.45 if dark_mode else 0.3, color=grid_color)
|
||||||
ax1.tick_params(labelsize=8)
|
|
||||||
ax1.set_xlim(0, 105)
|
ax1.set_xlim(0, 105)
|
||||||
|
|
||||||
# 纵坐标范围由用户参数控制
|
# 纵坐标范围由用户参数控制
|
||||||
@@ -211,7 +249,8 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
ax2.plot(
|
ax2.plot(
|
||||||
grayscale,
|
grayscale,
|
||||||
y_measured,
|
y_measured,
|
||||||
"r-o",
|
color=y_line_color,
|
||||||
|
marker="o",
|
||||||
label="屏本体",
|
label="屏本体",
|
||||||
linewidth=2,
|
linewidth=2,
|
||||||
markersize=4,
|
markersize=4,
|
||||||
@@ -228,19 +267,19 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="bottom",
|
va="bottom",
|
||||||
fontsize=7,
|
fontsize=7,
|
||||||
color="red",
|
color=y_line_color,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=0.2",
|
boxstyle="round,pad=0.2",
|
||||||
facecolor="white",
|
facecolor=palette["card_bg"],
|
||||||
edgecolor="red",
|
edgecolor=y_line_color,
|
||||||
alpha=0.8,
|
alpha=0.92 if dark_mode else 0.85,
|
||||||
linewidth=0.5,
|
linewidth=0.8,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
ax2.axhline(
|
ax2.axhline(
|
||||||
y=y_ideal,
|
y=y_ideal,
|
||||||
color="green",
|
color=ideal_line_color,
|
||||||
linestyle="--",
|
linestyle="--",
|
||||||
linewidth=1.5,
|
linewidth=1.5,
|
||||||
label=f"y-ideal ({y_ideal:.4f})",
|
label=f"y-ideal ({y_ideal:.4f})",
|
||||||
@@ -248,30 +287,34 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
)
|
)
|
||||||
ax2.axhline(
|
ax2.axhline(
|
||||||
y=y_low,
|
y=y_low,
|
||||||
color="orange",
|
color=y_tol_color,
|
||||||
linestyle=":",
|
linestyle=":",
|
||||||
linewidth=1,
|
linewidth=1,
|
||||||
alpha=0.7,
|
alpha=0.95 if dark_mode else 0.7,
|
||||||
label=f"y-low ({y_low:.4f})",
|
label=f"y-low ({y_low:.4f})",
|
||||||
zorder=2,
|
zorder=2,
|
||||||
)
|
)
|
||||||
ax2.axhline(
|
ax2.axhline(
|
||||||
y=y_high,
|
y=y_high,
|
||||||
color="orange",
|
color=y_tol_color,
|
||||||
linestyle=":",
|
linestyle=":",
|
||||||
linewidth=1,
|
linewidth=1,
|
||||||
alpha=0.7,
|
alpha=0.95 if dark_mode else 0.7,
|
||||||
label=f"y-high ({y_high:.4f})",
|
label=f"y-high ({y_high:.4f})",
|
||||||
zorder=2,
|
zorder=2,
|
||||||
)
|
)
|
||||||
ax2.fill_between(
|
ax2.fill_between(
|
||||||
full_grayscale, y_low, y_high, alpha=0.15, color="orange", zorder=1
|
full_grayscale,
|
||||||
|
y_low,
|
||||||
|
y_high,
|
||||||
|
alpha=0.22 if dark_mode else 0.15,
|
||||||
|
color=y_tol_color,
|
||||||
|
zorder=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
ax2.set_xlabel("灰阶 (%)", fontsize=9)
|
ax2.set_xlabel("灰阶 (%)", fontsize=9, color=axis_text)
|
||||||
ax2.set_ylabel("CIE y", fontsize=9)
|
ax2.set_ylabel("CIE y", fontsize=9, color=axis_text)
|
||||||
ax2.grid(True, linestyle="--", alpha=0.3)
|
ax2.grid(True, linestyle="--", alpha=0.45 if dark_mode else 0.3, color=grid_color)
|
||||||
ax2.tick_params(labelsize=8)
|
|
||||||
ax2.set_xlim(0, 105)
|
ax2.set_xlim(0, 105)
|
||||||
|
|
||||||
# 纵坐标范围由用户参数控制
|
# 纵坐标范围由用户参数控制
|
||||||
@@ -307,6 +350,7 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
fontsize=12,
|
fontsize=12,
|
||||||
y=0.98,
|
y=0.98,
|
||||||
fontweight="bold",
|
fontweight="bold",
|
||||||
|
color=palette["fg"],
|
||||||
)
|
)
|
||||||
|
|
||||||
self.cct_fig.subplots_adjust(
|
self.cct_fig.subplots_adjust(
|
||||||
@@ -317,12 +361,25 @@ def plot_cct(self: "PQAutomationApp", test_type):
|
|||||||
hspace=0.30,
|
hspace=0.30,
|
||||||
)
|
)
|
||||||
|
|
||||||
ax1.legend(
|
legend1 = ax1.legend(
|
||||||
fontsize=7, loc="center left", bbox_to_anchor=(1.05, 0.5), framealpha=1.0
|
fontsize=7,
|
||||||
|
loc="center left",
|
||||||
|
bbox_to_anchor=(1.05, 0.5),
|
||||||
|
framealpha=0.92 if dark_mode else 1.0,
|
||||||
|
facecolor=legend_bg,
|
||||||
|
edgecolor=legend_edge,
|
||||||
)
|
)
|
||||||
ax2.legend(
|
legend2 = ax2.legend(
|
||||||
fontsize=7, loc="center left", bbox_to_anchor=(1.05, 0.5), framealpha=1.0
|
fontsize=7,
|
||||||
|
loc="center left",
|
||||||
|
bbox_to_anchor=(1.05, 0.5),
|
||||||
|
framealpha=0.92 if dark_mode else 1.0,
|
||||||
|
facecolor=legend_bg,
|
||||||
|
edgecolor=legend_edge,
|
||||||
)
|
)
|
||||||
|
for legend in (legend1, legend2):
|
||||||
|
for text in legend.get_texts():
|
||||||
|
text.set_color(axis_text)
|
||||||
|
|
||||||
self.cct_canvas.draw()
|
self.cct_canvas.draw()
|
||||||
self.chart_notebook.select(self.cct_chart_frame)
|
self.chart_notebook.select(self.cct_chart_frame)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_contrast 原样搬迁
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from matplotlib.patches import Rectangle
|
from matplotlib.patches import Rectangle
|
||||||
|
from app.views.modern_styles import get_theme_palette
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
@@ -14,9 +15,12 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
|
def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
|
||||||
"""绘制对比度测试结果 - 固定布局版本"""
|
"""绘制对比度测试结果 - 固定布局版本"""
|
||||||
|
palette = get_theme_palette()
|
||||||
|
|
||||||
# 清空并重置
|
# 清空并重置
|
||||||
self.contrast_ax.clear()
|
self.contrast_ax.clear()
|
||||||
|
self.contrast_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
self.contrast_ax.set_facecolor(palette["card_bg"])
|
||||||
self.contrast_ax.set_xlim(0, 1)
|
self.contrast_ax.set_xlim(0, 1)
|
||||||
self.contrast_ax.set_ylim(0, 1)
|
self.contrast_ax.set_ylim(0, 1)
|
||||||
self.contrast_ax.axis("off")
|
self.contrast_ax.axis("off")
|
||||||
@@ -51,6 +55,7 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
|
|||||||
fontsize=12,
|
fontsize=12,
|
||||||
y=0.98,
|
y=0.98,
|
||||||
fontweight="bold",
|
fontweight="bold",
|
||||||
|
color=palette["fg"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# ========== 中央大对比度卡片 ==========
|
# ========== 中央大对比度卡片 ==========
|
||||||
@@ -107,16 +112,16 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
|
|||||||
"title": "白场亮度",
|
"title": "白场亮度",
|
||||||
"value": f"{max_lum:.2f}",
|
"value": f"{max_lum:.2f}",
|
||||||
"unit": "cd/m²",
|
"unit": "cd/m²",
|
||||||
"color": "#E3F2FD",
|
"color": palette["surface_alt_bg"],
|
||||||
"edge_color": "#2196F3",
|
"edge_color": palette["primary"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": start_x + card_width + gap,
|
"x": start_x + card_width + gap,
|
||||||
"title": "黑场亮度",
|
"title": "黑场亮度",
|
||||||
"value": f"{min_lum:.4f}",
|
"value": f"{min_lum:.4f}",
|
||||||
"unit": "cd/m²",
|
"unit": "cd/m²",
|
||||||
"color": "#F3E5F5",
|
"color": palette["card_bg"],
|
||||||
"edge_color": "#9C27B0",
|
"edge_color": palette["secondary"],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -142,6 +147,7 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
|
|||||||
va="top",
|
va="top",
|
||||||
fontsize=10,
|
fontsize=10,
|
||||||
fontweight="bold",
|
fontweight="bold",
|
||||||
|
color=palette["fg"],
|
||||||
transform=self.contrast_ax.transAxes,
|
transform=self.contrast_ax.transAxes,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -154,6 +160,7 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
|
|||||||
va="center",
|
va="center",
|
||||||
fontsize=16,
|
fontsize=16,
|
||||||
fontweight="bold",
|
fontweight="bold",
|
||||||
|
color=palette["fg"],
|
||||||
transform=self.contrast_ax.transAxes,
|
transform=self.contrast_ax.transAxes,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -165,7 +172,7 @@ def plot_contrast(self: "PQAutomationApp", contrast_data, test_type):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="bottom",
|
va="bottom",
|
||||||
fontsize=9,
|
fontsize=9,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.contrast_ax.transAxes,
|
transform=self.contrast_ax.transAxes,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_eotf 原样搬迁。
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from app.views.modern_styles import get_theme_palette
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
@@ -14,15 +15,21 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
def plot_eotf(self: "PQAutomationApp", L_bar, results_with_eotf_list, test_type):
|
def plot_eotf(self: "PQAutomationApp", L_bar, results_with_eotf_list, test_type):
|
||||||
"""绘制 EOTF 曲线 + 数据表格(HDR 专用,包含实测亮度)"""
|
"""绘制 EOTF 曲线 + 数据表格(HDR 专用,包含实测亮度)"""
|
||||||
|
palette = get_theme_palette()
|
||||||
|
|
||||||
# ========== 1. 清空并重置左侧曲线 ==========
|
# ========== 1. 清空并重置左侧曲线 ==========
|
||||||
self.eotf_ax.clear()
|
self.eotf_ax.clear()
|
||||||
|
self.eotf_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
self.eotf_ax.set_facecolor(palette["card_bg"])
|
||||||
self.eotf_ax.set_xlim(0, 105)
|
self.eotf_ax.set_xlim(0, 105)
|
||||||
self.eotf_ax.set_ylim(0, 1.1)
|
self.eotf_ax.set_ylim(0, 1.1)
|
||||||
self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
||||||
self.eotf_ax.set_ylabel("L_bar", fontsize=10)
|
self.eotf_ax.set_ylabel("L_bar", fontsize=10)
|
||||||
self.eotf_ax.grid(True, linestyle="--", alpha=0.3)
|
self.eotf_ax.grid(True, linestyle="--", alpha=0.3)
|
||||||
self.eotf_ax.tick_params(labelsize=9)
|
self.eotf_ax.tick_params(labelsize=9)
|
||||||
|
self.eotf_ax.tick_params(colors=palette["fg"])
|
||||||
|
for spine in self.eotf_ax.spines.values():
|
||||||
|
spine.set_color(palette["border"])
|
||||||
|
|
||||||
# 生成横坐标(灰阶百分比)
|
# 生成横坐标(灰阶百分比)
|
||||||
x_values = np.linspace(0, 100, len(L_bar))
|
x_values = np.linspace(0, 100, len(L_bar))
|
||||||
@@ -120,17 +127,17 @@ def plot_eotf(self: "PQAutomationApp", L_bar, results_with_eotf_list, test_type)
|
|||||||
# 表头样式
|
# 表头样式
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
cell = table[(0, i)]
|
cell = table[(0, i)]
|
||||||
cell.set_facecolor("#4472C4")
|
cell.set_facecolor(palette["primary"])
|
||||||
cell.set_text_props(weight="bold", color="white")
|
cell.set_text_props(weight="bold", color=palette["select_fg"])
|
||||||
|
|
||||||
# 数据行交替颜色
|
# 数据行交替颜色
|
||||||
for i in range(1, len(table_data)):
|
for i in range(1, len(table_data)):
|
||||||
for j in range(4):
|
for j in range(4):
|
||||||
cell = table[(i, j)]
|
cell = table[(i, j)]
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
cell.set_facecolor("#E7E6E6")
|
cell.set_facecolor(palette["surface_alt_bg"])
|
||||||
else:
|
else:
|
||||||
cell.set_facecolor("#FFFFFF")
|
cell.set_facecolor(palette["card_bg"])
|
||||||
|
|
||||||
# ========== 3. 总标题 ==========
|
# ========== 3. 总标题 ==========
|
||||||
test_type_name = self.get_test_type_name(test_type)
|
test_type_name = self.get_test_type_name(test_type)
|
||||||
@@ -139,6 +146,7 @@ def plot_eotf(self: "PQAutomationApp", L_bar, results_with_eotf_list, test_type)
|
|||||||
fontsize=12,
|
fontsize=12,
|
||||||
y=0.98,
|
y=0.98,
|
||||||
fontweight="bold",
|
fontweight="bold",
|
||||||
|
color=palette["fg"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# 选中 EOTF Tab
|
# 选中 EOTF Tab
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Step 2 重构:从 pqAutomationApp.PQAutomationApp.plot_gamma 原样搬迁。
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from app.views.modern_styles import get_theme_palette
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
@@ -11,18 +12,44 @@ if TYPE_CHECKING:
|
|||||||
from pqAutomationApp import PQAutomationApp
|
from pqAutomationApp import PQAutomationApp
|
||||||
|
|
||||||
|
|
||||||
|
def _is_dark_palette(palette: dict[str, str]) -> bool:
|
||||||
|
"""根据主题背景色亮度判断是否深色主题。"""
|
||||||
|
bg = palette.get("bg", "#FFFFFF").lstrip("#")
|
||||||
|
try:
|
||||||
|
r = int(bg[0:2], 16)
|
||||||
|
g = int(bg[2:4], 16)
|
||||||
|
b = int(bg[4:6], 16)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return (r * 299 + g * 587 + b * 114) / 1000 < 128
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_gamma, test_type):
|
def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_gamma, test_type):
|
||||||
"""绘制Gamma曲线 + 数据表格(包含实测亮度)"""
|
"""绘制Gamma曲线 + 数据表格(包含实测亮度)"""
|
||||||
|
palette = get_theme_palette()
|
||||||
|
dark_mode = _is_dark_palette(palette)
|
||||||
|
line_actual = "#3FA7FF" if dark_mode else "#0A4BFF"
|
||||||
|
line_ideal = "#FF6B6B" if dark_mode else "#D62828"
|
||||||
|
grid_color = "#566070" if dark_mode else "#B8BDC3"
|
||||||
|
legend_bg = "#131821" if dark_mode else "#FFFFFF"
|
||||||
|
legend_edge = "#A4B2C6" if dark_mode else palette["border"]
|
||||||
|
table_edge = "#738196" if dark_mode else palette["border"]
|
||||||
|
table_body_fg = "#EEF3FA" if dark_mode else palette["fg"]
|
||||||
|
|
||||||
# ========== 1. 清空并重置左侧曲线 ==========
|
# ========== 1. 清空并重置左侧曲线 ==========
|
||||||
self.gamma_ax.clear()
|
self.gamma_ax.clear()
|
||||||
|
self.gamma_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
self.gamma_ax.set_facecolor(palette["card_bg"])
|
||||||
self.gamma_ax.set_xlim(0, 105)
|
self.gamma_ax.set_xlim(0, 105)
|
||||||
self.gamma_ax.set_ylim(0, 1.1)
|
self.gamma_ax.set_ylim(0, 1.1)
|
||||||
self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10, color=palette["fg"])
|
||||||
self.gamma_ax.set_ylabel("L_bar", fontsize=10)
|
self.gamma_ax.set_ylabel("L_bar", fontsize=10, color=palette["fg"])
|
||||||
self.gamma_ax.grid(True, linestyle="--", alpha=0.3)
|
self.gamma_ax.grid(True, linestyle="--", alpha=0.45 if dark_mode else 0.3, color=grid_color)
|
||||||
self.gamma_ax.tick_params(labelsize=9)
|
self.gamma_ax.tick_params(labelsize=9)
|
||||||
|
self.gamma_ax.tick_params(colors=palette["fg"])
|
||||||
|
for spine in self.gamma_ax.spines.values():
|
||||||
|
spine.set_color(palette["border"])
|
||||||
|
|
||||||
# 生成横坐标(灰阶百分比)
|
# 生成横坐标(灰阶百分比)
|
||||||
x_values = np.linspace(0, 100, len(L_bar))
|
x_values = np.linspace(0, 100, len(L_bar))
|
||||||
@@ -46,7 +73,8 @@ def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_g
|
|||||||
self.gamma_ax.plot(
|
self.gamma_ax.plot(
|
||||||
x_values,
|
x_values,
|
||||||
L_bar,
|
L_bar,
|
||||||
"b-o",
|
color=line_actual,
|
||||||
|
marker="o",
|
||||||
label=f"实测 (平均γ={avg_gamma:.2f})",
|
label=f"实测 (平均γ={avg_gamma:.2f})",
|
||||||
linewidth=2,
|
linewidth=2,
|
||||||
markersize=4,
|
markersize=4,
|
||||||
@@ -58,15 +86,24 @@ def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_g
|
|||||||
self.gamma_ax.plot(
|
self.gamma_ax.plot(
|
||||||
x_values,
|
x_values,
|
||||||
ideal_L_bar,
|
ideal_L_bar,
|
||||||
"r--",
|
color=line_ideal,
|
||||||
|
linestyle="--",
|
||||||
label=f"理想 (γ={target_gamma})",
|
label=f"理想 (γ={target_gamma})",
|
||||||
linewidth=2,
|
linewidth=2,
|
||||||
alpha=0.7,
|
alpha=0.9 if dark_mode else 0.7,
|
||||||
zorder=3,
|
zorder=3,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 图例
|
# 图例
|
||||||
self.gamma_ax.legend(fontsize=9, loc="upper left", framealpha=0.95)
|
legend = self.gamma_ax.legend(
|
||||||
|
fontsize=9,
|
||||||
|
loc="upper left",
|
||||||
|
framealpha=0.9 if dark_mode else 0.95,
|
||||||
|
facecolor=legend_bg,
|
||||||
|
edgecolor=legend_edge,
|
||||||
|
)
|
||||||
|
for text in legend.get_texts():
|
||||||
|
text.set_color(palette["fg"])
|
||||||
|
|
||||||
# ========== 2. 清空并绘制右侧表格 ==========
|
# ========== 2. 清空并绘制右侧表格 ==========
|
||||||
self.gamma_table_ax.clear()
|
self.gamma_table_ax.clear()
|
||||||
@@ -120,17 +157,22 @@ def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_g
|
|||||||
# 表头样式
|
# 表头样式
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
cell = table[(0, i)]
|
cell = table[(0, i)]
|
||||||
cell.set_facecolor("#4472C4")
|
cell.set_facecolor(palette["primary"])
|
||||||
cell.set_text_props(weight="bold", color="white")
|
cell.set_text_props(weight="bold", color=palette["select_fg"])
|
||||||
|
cell.set_edgecolor(table_edge)
|
||||||
|
cell.set_linewidth(0.8)
|
||||||
|
|
||||||
# 数据行交替颜色
|
# 数据行交替颜色
|
||||||
for i in range(1, len(table_data)):
|
for i in range(1, len(table_data)):
|
||||||
for j in range(4):
|
for j in range(4):
|
||||||
cell = table[(i, j)]
|
cell = table[(i, j)]
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
cell.set_facecolor("#E7E6E6")
|
cell.set_facecolor(palette["surface_alt_bg"])
|
||||||
else:
|
else:
|
||||||
cell.set_facecolor("#FFFFFF")
|
cell.set_facecolor(palette["card_bg"])
|
||||||
|
cell.set_text_props(color=table_body_fg)
|
||||||
|
cell.set_edgecolor(table_edge)
|
||||||
|
cell.set_linewidth(0.6)
|
||||||
|
|
||||||
# ========== 3. 总标题 ==========
|
# ========== 3. 总标题 ==========
|
||||||
test_type_name = self.get_test_type_name(test_type)
|
test_type_name = self.get_test_type_name(test_type)
|
||||||
@@ -139,6 +181,7 @@ def plot_gamma(self: "PQAutomationApp", L_bar, results_with_gamma_list, target_g
|
|||||||
fontsize=12,
|
fontsize=12,
|
||||||
y=0.98,
|
y=0.98,
|
||||||
fontweight="bold",
|
fontweight="bold",
|
||||||
|
color=palette["fg"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# ========== 4. 绘制到画布 ==========
|
# ========== 4. 绘制到画布 ==========
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ def _style_axes(ax, *, title, xlabel, ylabel, xlim, ylim, dark_mode):
|
|||||||
ax.set_ylabel(ylabel, fontsize=10, color=text)
|
ax.set_ylabel(ylabel, fontsize=10, color=text)
|
||||||
ax.set_xlim(*xlim)
|
ax.set_xlim(*xlim)
|
||||||
ax.set_ylim(*ylim)
|
ax.set_ylim(*ylim)
|
||||||
ax.set_aspect("equal", adjustable="datalim")
|
ax.set_aspect("equal", adjustable="box")
|
||||||
ax.grid(True, linestyle=":", linewidth=0.7, color=grid, alpha=0.32)
|
ax.grid(True, linestyle=":", linewidth=0.7, color=grid, alpha=0.32)
|
||||||
ax.tick_params(axis="both", labelsize=9, colors=text)
|
ax.tick_params(axis="both", labelsize=9, colors=text)
|
||||||
for spine in ax.spines.values():
|
for spine in ax.spines.values():
|
||||||
@@ -193,8 +193,10 @@ def _blit_background(ax, background, bbox):
|
|||||||
ax.imshow(
|
ax.imshow(
|
||||||
background,
|
background,
|
||||||
extent=(xmin, xmax, ymin, ymax),
|
extent=(xmin, xmax, ymin, ymax),
|
||||||
origin="upper", # canvas.buffer_rgba 行 0 为顶部
|
# gamut_background._render_chromaticity 已做过 np.flipud,
|
||||||
interpolation="bicubic",
|
# 这里必须使用 lower 才能与真实色度坐标方向一致。
|
||||||
|
origin="lower",
|
||||||
|
interpolation="bilinear",
|
||||||
zorder=0,
|
zorder=0,
|
||||||
aspect="auto", # 由 _style_axes 的 set_aspect("equal") 控制
|
aspect="auto", # 由 _style_axes 的 set_aspect("equal") 控制
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import ttkbootstrap as ttk
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||||
from app.views.pq_debug_panel import PQDebugPanel
|
from app.views.pq_debug_panel import PQDebugPanel
|
||||||
|
from app.views.modern_styles import get_theme_palette
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
@@ -19,8 +20,7 @@ if TYPE_CHECKING:
|
|||||||
def _result_bg_color() -> str:
|
def _result_bg_color() -> str:
|
||||||
"""根据当前主题返回结果图背景色。"""
|
"""根据当前主题返回结果图背景色。"""
|
||||||
try:
|
try:
|
||||||
from app.views.theme_manager import is_dark
|
return get_theme_palette()["bg"]
|
||||||
return "#1B1F24" if is_dark() else "#FFFFFF"
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return "#FFFFFF"
|
return "#FFFFFF"
|
||||||
|
|
||||||
@@ -55,6 +55,19 @@ def apply_result_chart_theme(self: "PQAutomationApp"):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_axes_theme(ax, palette, *, title=None, xlabel=None, ylabel=None):
|
||||||
|
ax.set_facecolor(palette["card_bg"])
|
||||||
|
for spine in ax.spines.values():
|
||||||
|
spine.set_color(palette["border"])
|
||||||
|
if title is not None:
|
||||||
|
ax.set_title(title, color=palette["fg"])
|
||||||
|
if xlabel is not None:
|
||||||
|
ax.set_xlabel(xlabel, color=palette["fg"])
|
||||||
|
if ylabel is not None:
|
||||||
|
ax.set_ylabel(ylabel, color=palette["fg"])
|
||||||
|
ax.tick_params(axis="both", colors=palette["fg"])
|
||||||
|
|
||||||
|
|
||||||
def init_gamut_chart(self: "PQAutomationApp"):
|
def init_gamut_chart(self: "PQAutomationApp"):
|
||||||
"""初始化色域图表 - 手动设置subplot位置,完全避免重叠"""
|
"""初始化色域图表 - 手动设置subplot位置,完全避免重叠"""
|
||||||
container = ttk.Frame(self.gamut_chart_frame)
|
container = ttk.Frame(self.gamut_chart_frame)
|
||||||
@@ -154,8 +167,10 @@ def init_gamma_chart(self: "PQAutomationApp"):
|
|||||||
"""初始化Gamma曲线图表 - 左侧曲线 + 右侧表格(4列 + 通用说明)"""
|
"""初始化Gamma曲线图表 - 左侧曲线 + 右侧表格(4列 + 通用说明)"""
|
||||||
container = ttk.Frame(self.gamma_chart_frame)
|
container = ttk.Frame(self.gamma_chart_frame)
|
||||||
container.pack(expand=True, fill=tk.BOTH)
|
container.pack(expand=True, fill=tk.BOTH)
|
||||||
|
palette = get_theme_palette()
|
||||||
|
|
||||||
self.gamma_fig = plt.Figure(figsize=(12, 6), dpi=100, constrained_layout=False)
|
self.gamma_fig = plt.Figure(figsize=(12, 6), dpi=100, constrained_layout=False)
|
||||||
|
self.gamma_fig.patch.set_facecolor(palette["bg"])
|
||||||
self.gamma_canvas = FigureCanvasTkAgg(self.gamma_fig, master=container)
|
self.gamma_canvas = FigureCanvasTkAgg(self.gamma_fig, master=container)
|
||||||
|
|
||||||
canvas_widget = self.gamma_canvas.get_tk_widget()
|
canvas_widget = self.gamma_canvas.get_tk_widget()
|
||||||
@@ -163,6 +178,7 @@ def init_gamma_chart(self: "PQAutomationApp"):
|
|||||||
|
|
||||||
# 左侧:Gamma 曲线
|
# 左侧:Gamma 曲线
|
||||||
self.gamma_ax = self.gamma_fig.add_axes([0.08, 0.12, 0.50, 0.78])
|
self.gamma_ax = self.gamma_fig.add_axes([0.08, 0.12, 0.50, 0.78])
|
||||||
|
_apply_axes_theme(self.gamma_ax, palette, xlabel="灰阶 (%)", ylabel="L_bar")
|
||||||
self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
||||||
self.gamma_ax.set_ylabel("L_bar", fontsize=10)
|
self.gamma_ax.set_ylabel("L_bar", fontsize=10)
|
||||||
self.gamma_ax.set_xlim(0, 105)
|
self.gamma_ax.set_xlim(0, 105)
|
||||||
@@ -182,10 +198,13 @@ def init_gamma_chart(self: "PQAutomationApp"):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="center",
|
va="center",
|
||||||
fontsize=10,
|
fontsize=10,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.gamma_ax.transAxes,
|
transform=self.gamma_ax.transAxes,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=1", facecolor="white", edgecolor="gray", alpha=0.8
|
boxstyle="round,pad=1",
|
||||||
|
facecolor=palette["card_bg"],
|
||||||
|
edgecolor=palette["border"],
|
||||||
|
alpha=0.95,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -223,17 +242,17 @@ def init_gamma_chart(self: "PQAutomationApp"):
|
|||||||
# 表头样式
|
# 表头样式
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
cell = table[(0, i)]
|
cell = table[(0, i)]
|
||||||
cell.set_facecolor("#4472C4")
|
cell.set_facecolor(palette["primary"])
|
||||||
cell.set_text_props(weight="bold", color="white", fontsize=7)
|
cell.set_text_props(weight="bold", color=palette["select_fg"], fontsize=7)
|
||||||
|
|
||||||
# 数据行交替颜色
|
# 数据行交替颜色
|
||||||
for i in range(1, len(table_data)):
|
for i in range(1, len(table_data)):
|
||||||
for j in range(4):
|
for j in range(4):
|
||||||
cell = table[(i, j)]
|
cell = table[(i, j)]
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
cell.set_facecolor("#E7E6E6")
|
cell.set_facecolor(palette["surface_alt_bg"])
|
||||||
else:
|
else:
|
||||||
cell.set_facecolor("#FFFFFF")
|
cell.set_facecolor(palette["card_bg"])
|
||||||
|
|
||||||
# 底部说明
|
# 底部说明
|
||||||
self.gamma_table_ax.text(
|
self.gamma_table_ax.text(
|
||||||
@@ -246,25 +265,27 @@ def init_gamma_chart(self: "PQAutomationApp"):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="bottom",
|
va="bottom",
|
||||||
fontsize=7,
|
fontsize=7,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.gamma_table_ax.transAxes,
|
transform=self.gamma_table_ax.transAxes,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=0.5",
|
boxstyle="round,pad=0.5",
|
||||||
facecolor="lightyellow",
|
facecolor=palette["surface_alt_bg"],
|
||||||
edgecolor="gray",
|
edgecolor=palette["border"],
|
||||||
alpha=0.8,
|
alpha=0.95,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.gamma_fig.suptitle("Gamma曲线 + 数据表格", fontsize=12, y=0.98)
|
self.gamma_fig.suptitle("Gamma曲线 + 数据表格", fontsize=12, y=0.98, color=palette["fg"])
|
||||||
self.gamma_canvas.draw()
|
self.gamma_canvas.draw()
|
||||||
|
|
||||||
def init_eotf_chart(self: "PQAutomationApp"):
|
def init_eotf_chart(self: "PQAutomationApp"):
|
||||||
"""初始化 EOTF 曲线图表(HDR 专用)- 左侧曲线 + 右侧表格(4列)"""
|
"""初始化 EOTF 曲线图表(HDR 专用)- 左侧曲线 + 右侧表格(4列)"""
|
||||||
container = ttk.Frame(self.eotf_chart_frame)
|
container = ttk.Frame(self.eotf_chart_frame)
|
||||||
container.pack(expand=True, fill=tk.BOTH)
|
container.pack(expand=True, fill=tk.BOTH)
|
||||||
|
palette = get_theme_palette()
|
||||||
|
|
||||||
self.eotf_fig = plt.Figure(figsize=(12, 6), dpi=100, constrained_layout=False)
|
self.eotf_fig = plt.Figure(figsize=(12, 6), dpi=100, constrained_layout=False)
|
||||||
|
self.eotf_fig.patch.set_facecolor(palette["bg"])
|
||||||
self.eotf_canvas = FigureCanvasTkAgg(self.eotf_fig, master=container)
|
self.eotf_canvas = FigureCanvasTkAgg(self.eotf_fig, master=container)
|
||||||
|
|
||||||
canvas_widget = self.eotf_canvas.get_tk_widget()
|
canvas_widget = self.eotf_canvas.get_tk_widget()
|
||||||
@@ -272,6 +293,7 @@ def init_eotf_chart(self: "PQAutomationApp"):
|
|||||||
|
|
||||||
# 左侧:EOTF 曲线
|
# 左侧:EOTF 曲线
|
||||||
self.eotf_ax = self.eotf_fig.add_axes([0.08, 0.12, 0.50, 0.78])
|
self.eotf_ax = self.eotf_fig.add_axes([0.08, 0.12, 0.50, 0.78])
|
||||||
|
_apply_axes_theme(self.eotf_ax, palette, xlabel="灰阶 (%)", ylabel="L_bar (归一化亮度)")
|
||||||
self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
||||||
self.eotf_ax.set_ylabel("L_bar (归一化亮度)", fontsize=10)
|
self.eotf_ax.set_ylabel("L_bar (归一化亮度)", fontsize=10)
|
||||||
self.eotf_ax.set_xlim(0, 105)
|
self.eotf_ax.set_xlim(0, 105)
|
||||||
@@ -287,10 +309,13 @@ def init_eotf_chart(self: "PQAutomationApp"):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="center",
|
va="center",
|
||||||
fontsize=11,
|
fontsize=11,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.eotf_ax.transAxes,
|
transform=self.eotf_ax.transAxes,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=1", facecolor="white", edgecolor="gray", alpha=0.8
|
boxstyle="round,pad=1",
|
||||||
|
facecolor=palette["card_bg"],
|
||||||
|
edgecolor=palette["border"],
|
||||||
|
alpha=0.95,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -328,17 +353,17 @@ def init_eotf_chart(self: "PQAutomationApp"):
|
|||||||
# 表头样式
|
# 表头样式
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
cell = table[(0, i)]
|
cell = table[(0, i)]
|
||||||
cell.set_facecolor("#4472C4")
|
cell.set_facecolor(palette["primary"])
|
||||||
cell.set_text_props(weight="bold", color="white", fontsize=7)
|
cell.set_text_props(weight="bold", color=palette["select_fg"], fontsize=7)
|
||||||
|
|
||||||
# 数据行交替颜色
|
# 数据行交替颜色
|
||||||
for i in range(1, len(table_data)):
|
for i in range(1, len(table_data)):
|
||||||
for j in range(4):
|
for j in range(4):
|
||||||
cell = table[(i, j)]
|
cell = table[(i, j)]
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
cell.set_facecolor("#E7E6E6")
|
cell.set_facecolor(palette["surface_alt_bg"])
|
||||||
else:
|
else:
|
||||||
cell.set_facecolor("#FFFFFF")
|
cell.set_facecolor(palette["card_bg"])
|
||||||
|
|
||||||
# 底部说明
|
# 底部说明
|
||||||
self.eotf_table_ax.text(
|
self.eotf_table_ax.text(
|
||||||
@@ -351,25 +376,27 @@ def init_eotf_chart(self: "PQAutomationApp"):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="bottom",
|
va="bottom",
|
||||||
fontsize=7,
|
fontsize=7,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.eotf_table_ax.transAxes,
|
transform=self.eotf_table_ax.transAxes,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=0.5",
|
boxstyle="round,pad=0.5",
|
||||||
facecolor="lightyellow",
|
facecolor=palette["surface_alt_bg"],
|
||||||
edgecolor="gray",
|
edgecolor=palette["border"],
|
||||||
alpha=0.8,
|
alpha=0.95,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.eotf_fig.suptitle("EOTF 曲线 + 数据表格", fontsize=12, y=0.98)
|
self.eotf_fig.suptitle("EOTF 曲线 + 数据表格", fontsize=12, y=0.98, color=palette["fg"])
|
||||||
self.eotf_canvas.draw()
|
self.eotf_canvas.draw()
|
||||||
|
|
||||||
def init_cct_chart(self: "PQAutomationApp"):
|
def init_cct_chart(self: "PQAutomationApp"):
|
||||||
"""初始化色度坐标图表 - 正向横坐标,标题居中最上方"""
|
"""初始化色度坐标图表 - 正向横坐标,标题居中最上方"""
|
||||||
container = ttk.Frame(self.cct_chart_frame)
|
container = ttk.Frame(self.cct_chart_frame)
|
||||||
container.pack(expand=True)
|
container.pack(expand=True)
|
||||||
|
palette = get_theme_palette()
|
||||||
|
|
||||||
self.cct_fig = plt.Figure(figsize=(8, 6), dpi=100, tight_layout=False)
|
self.cct_fig = plt.Figure(figsize=(8, 6), dpi=100, tight_layout=False)
|
||||||
|
self.cct_fig.patch.set_facecolor(palette["bg"])
|
||||||
self.cct_canvas = FigureCanvasTkAgg(self.cct_fig, master=container)
|
self.cct_canvas = FigureCanvasTkAgg(self.cct_fig, master=container)
|
||||||
|
|
||||||
canvas_widget = self.cct_canvas.get_tk_widget()
|
canvas_widget = self.cct_canvas.get_tk_widget()
|
||||||
@@ -378,7 +405,9 @@ def init_cct_chart(self: "PQAutomationApp"):
|
|||||||
canvas_widget.pack_propagate(False)
|
canvas_widget.pack_propagate(False)
|
||||||
|
|
||||||
self.cct_ax1 = self.cct_fig.add_subplot(211)
|
self.cct_ax1 = self.cct_fig.add_subplot(211)
|
||||||
|
self.cct_ax1.set_facecolor(palette["card_bg"])
|
||||||
self.cct_ax2 = self.cct_fig.add_subplot(212)
|
self.cct_ax2 = self.cct_fig.add_subplot(212)
|
||||||
|
self.cct_ax2.set_facecolor(palette["card_bg"])
|
||||||
|
|
||||||
# 上图:x coordinates
|
# 上图:x coordinates
|
||||||
self.cct_ax1.set_xlabel("灰阶 (%)", fontsize=9)
|
self.cct_ax1.set_xlabel("灰阶 (%)", fontsize=9)
|
||||||
@@ -397,7 +426,7 @@ def init_cct_chart(self: "PQAutomationApp"):
|
|||||||
self.cct_ax2.tick_params(labelsize=8)
|
self.cct_ax2.tick_params(labelsize=8)
|
||||||
|
|
||||||
# 调整标题位置:y=0.985(比色域/Gamma略高)
|
# 调整标题位置:y=0.985(比色域/Gamma略高)
|
||||||
self.cct_fig.suptitle("色度一致性测试", fontsize=12, y=0.985)
|
self.cct_fig.suptitle("色度一致性测试", fontsize=12, y=0.985, color=palette["fg"])
|
||||||
|
|
||||||
self.cct_fig.subplots_adjust(
|
self.cct_fig.subplots_adjust(
|
||||||
left=0.12,
|
left=0.12,
|
||||||
@@ -413,12 +442,14 @@ def init_contrast_chart(self: "PQAutomationApp"):
|
|||||||
"""初始化对比度图表 - 固定大小,居中显示"""
|
"""初始化对比度图表 - 固定大小,居中显示"""
|
||||||
container = ttk.Frame(self.contrast_chart_frame)
|
container = ttk.Frame(self.contrast_chart_frame)
|
||||||
container.pack(expand=True)
|
container.pack(expand=True)
|
||||||
|
palette = get_theme_palette()
|
||||||
|
|
||||||
self.contrast_fig = plt.Figure(
|
self.contrast_fig = plt.Figure(
|
||||||
figsize=(6, 6),
|
figsize=(6, 6),
|
||||||
dpi=100,
|
dpi=100,
|
||||||
tight_layout=False,
|
tight_layout=False,
|
||||||
)
|
)
|
||||||
|
self.contrast_fig.patch.set_facecolor(palette["bg"])
|
||||||
self.contrast_canvas = FigureCanvasTkAgg(self.contrast_fig, master=container)
|
self.contrast_canvas = FigureCanvasTkAgg(self.contrast_fig, master=container)
|
||||||
|
|
||||||
canvas_widget = self.contrast_canvas.get_tk_widget()
|
canvas_widget = self.contrast_canvas.get_tk_widget()
|
||||||
@@ -428,12 +459,13 @@ def init_contrast_chart(self: "PQAutomationApp"):
|
|||||||
canvas_widget.pack_propagate(False)
|
canvas_widget.pack_propagate(False)
|
||||||
|
|
||||||
self.contrast_ax = self.contrast_fig.add_subplot(111)
|
self.contrast_ax = self.contrast_fig.add_subplot(111)
|
||||||
|
self.contrast_ax.set_facecolor(palette["card_bg"])
|
||||||
self.contrast_ax.set_xlim(0, 1)
|
self.contrast_ax.set_xlim(0, 1)
|
||||||
self.contrast_ax.set_ylim(0, 1)
|
self.contrast_ax.set_ylim(0, 1)
|
||||||
self.contrast_ax.axis("off")
|
self.contrast_ax.axis("off")
|
||||||
|
|
||||||
# 调整标题位置:y=0.985
|
# 调整标题位置:y=0.985
|
||||||
self.contrast_fig.suptitle("对比度测试", fontsize=12, y=0.985)
|
self.contrast_fig.suptitle("对比度测试", fontsize=12, y=0.985, color=palette["fg"])
|
||||||
|
|
||||||
self.contrast_fig.subplots_adjust(
|
self.contrast_fig.subplots_adjust(
|
||||||
left=0.02,
|
left=0.02,
|
||||||
@@ -448,6 +480,7 @@ def init_accuracy_chart(self: "PQAutomationApp"):
|
|||||||
"""初始化色准图表 - 固定大小,居中显示"""
|
"""初始化色准图表 - 固定大小,居中显示"""
|
||||||
container = ttk.Frame(self.accuracy_chart_frame)
|
container = ttk.Frame(self.accuracy_chart_frame)
|
||||||
container.pack(expand=True, fill=tk.BOTH)
|
container.pack(expand=True, fill=tk.BOTH)
|
||||||
|
palette = get_theme_palette()
|
||||||
container.grid_rowconfigure(0, weight=1)
|
container.grid_rowconfigure(0, weight=1)
|
||||||
container.grid_rowconfigure(1, weight=0, minsize=220)
|
container.grid_rowconfigure(1, weight=0, minsize=220)
|
||||||
container.grid_columnconfigure(0, weight=1)
|
container.grid_columnconfigure(0, weight=1)
|
||||||
@@ -464,18 +497,27 @@ def init_accuracy_chart(self: "PQAutomationApp"):
|
|||||||
dpi=100,
|
dpi=100,
|
||||||
tight_layout=False,
|
tight_layout=False,
|
||||||
)
|
)
|
||||||
|
self.accuracy_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
try:
|
||||||
|
self.accuracy_fig.set_layout_engine(None)
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
self.accuracy_fig.set_tight_layout(False)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
self.accuracy_canvas = FigureCanvasTkAgg(self.accuracy_fig, master=plot_container)
|
self.accuracy_canvas = FigureCanvasTkAgg(self.accuracy_fig, master=plot_container)
|
||||||
|
|
||||||
canvas_widget = self.accuracy_canvas.get_tk_widget()
|
canvas_widget = self.accuracy_canvas.get_tk_widget()
|
||||||
canvas_widget.pack(fill=tk.BOTH, expand=True)
|
canvas_widget.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
self.accuracy_ax = self.accuracy_fig.add_subplot(111)
|
self.accuracy_ax = self.accuracy_fig.add_subplot(111)
|
||||||
|
self.accuracy_ax.set_facecolor(palette["card_bg"])
|
||||||
self.accuracy_ax.set_xlim(0, 1)
|
self.accuracy_ax.set_xlim(0, 1)
|
||||||
self.accuracy_ax.set_ylim(0, 1)
|
self.accuracy_ax.set_ylim(0, 1)
|
||||||
self.accuracy_ax.axis("off")
|
self.accuracy_ax.axis("off")
|
||||||
|
|
||||||
# 调整标题位置
|
# 调整标题位置
|
||||||
self.accuracy_fig.suptitle("色准测试", fontsize=12, y=0.985)
|
self.accuracy_fig.suptitle("色准测试", fontsize=12, y=0.985, color=palette["fg"])
|
||||||
|
|
||||||
self.accuracy_fig.subplots_adjust(
|
self.accuracy_fig.subplots_adjust(
|
||||||
left=0.05,
|
left=0.05,
|
||||||
@@ -616,6 +658,7 @@ def update_accuracy_result_table(self: "PQAutomationApp", accuracy_data, standar
|
|||||||
|
|
||||||
def clear_chart(self: "PQAutomationApp"):
|
def clear_chart(self: "PQAutomationApp"):
|
||||||
"""清空所有图表"""
|
"""清空所有图表"""
|
||||||
|
palette = get_theme_palette()
|
||||||
|
|
||||||
# ========== 1. 清空色域图表 ==========
|
# ========== 1. 清空色域图表 ==========
|
||||||
if hasattr(self, "gamut_ax_xy") and hasattr(self, "gamut_ax_uv"):
|
if hasattr(self, "gamut_ax_xy") and hasattr(self, "gamut_ax_uv"):
|
||||||
@@ -640,12 +683,17 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
if hasattr(self, "gamma_ax") and hasattr(self, "gamma_table_ax"):
|
if hasattr(self, "gamma_ax") and hasattr(self, "gamma_table_ax"):
|
||||||
# 清空左侧曲线
|
# 清空左侧曲线
|
||||||
self.gamma_ax.clear()
|
self.gamma_ax.clear()
|
||||||
|
self.gamma_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
self.gamma_ax.set_facecolor(palette["card_bg"])
|
||||||
self.gamma_ax.set_xlim(0, 105)
|
self.gamma_ax.set_xlim(0, 105)
|
||||||
self.gamma_ax.set_ylim(0, 1.1)
|
self.gamma_ax.set_ylim(0, 1.1)
|
||||||
self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
self.gamma_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
||||||
self.gamma_ax.set_ylabel("L_bar", fontsize=10)
|
self.gamma_ax.set_ylabel("L_bar", fontsize=10)
|
||||||
self.gamma_ax.grid(True, linestyle="--", alpha=0.3)
|
self.gamma_ax.grid(True, linestyle="--", alpha=0.3)
|
||||||
self.gamma_ax.tick_params(labelsize=9)
|
self.gamma_ax.tick_params(labelsize=9)
|
||||||
|
self.gamma_ax.tick_params(colors=palette["fg"])
|
||||||
|
for spine in self.gamma_ax.spines.values():
|
||||||
|
spine.set_color(palette["border"])
|
||||||
|
|
||||||
# 左侧提示
|
# 左侧提示
|
||||||
self.gamma_ax.text(
|
self.gamma_ax.text(
|
||||||
@@ -659,13 +707,13 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="center",
|
va="center",
|
||||||
fontsize=10,
|
fontsize=10,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.gamma_ax.transAxes,
|
transform=self.gamma_ax.transAxes,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=1",
|
boxstyle="round,pad=1",
|
||||||
facecolor="white",
|
facecolor=palette["card_bg"],
|
||||||
edgecolor="gray",
|
edgecolor=palette["border"],
|
||||||
alpha=0.8,
|
alpha=0.95,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -703,17 +751,17 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
# 表头样式
|
# 表头样式
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
cell = table[(0, i)]
|
cell = table[(0, i)]
|
||||||
cell.set_facecolor("#4472C4")
|
cell.set_facecolor(palette["primary"])
|
||||||
cell.set_text_props(weight="bold", color="white", fontsize=7)
|
cell.set_text_props(weight="bold", color=palette["select_fg"], fontsize=7)
|
||||||
|
|
||||||
# 数据行交替颜色
|
# 数据行交替颜色
|
||||||
for i in range(1, len(table_data)):
|
for i in range(1, len(table_data)):
|
||||||
for j in range(4):
|
for j in range(4):
|
||||||
cell = table[(i, j)]
|
cell = table[(i, j)]
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
cell.set_facecolor("#E7E6E6")
|
cell.set_facecolor(palette["surface_alt_bg"])
|
||||||
else:
|
else:
|
||||||
cell.set_facecolor("#FFFFFF")
|
cell.set_facecolor(palette["card_bg"])
|
||||||
|
|
||||||
# 底部说明
|
# 底部说明
|
||||||
self.gamma_table_ax.text(
|
self.gamma_table_ax.text(
|
||||||
@@ -726,29 +774,34 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="bottom",
|
va="bottom",
|
||||||
fontsize=7,
|
fontsize=7,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.gamma_table_ax.transAxes,
|
transform=self.gamma_table_ax.transAxes,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=0.5",
|
boxstyle="round,pad=0.5",
|
||||||
facecolor="lightyellow",
|
facecolor=palette["surface_alt_bg"],
|
||||||
edgecolor="gray",
|
edgecolor=palette["border"],
|
||||||
alpha=0.8,
|
alpha=0.95,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.gamma_fig.suptitle("Gamma曲线 + 数据表格", fontsize=12, y=0.98)
|
self.gamma_fig.suptitle("Gamma曲线 + 数据表格", fontsize=12, y=0.98, color=palette["fg"])
|
||||||
self.gamma_canvas.draw()
|
self.gamma_canvas.draw()
|
||||||
|
|
||||||
# ========== 3. 清空EOTF图表(4列)==========
|
# ========== 3. 清空EOTF图表(4列)==========
|
||||||
if hasattr(self, "eotf_ax") and hasattr(self, "eotf_table_ax"):
|
if hasattr(self, "eotf_ax") and hasattr(self, "eotf_table_ax"):
|
||||||
# 清空左侧曲线
|
# 清空左侧曲线
|
||||||
self.eotf_ax.clear()
|
self.eotf_ax.clear()
|
||||||
|
self.eotf_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
self.eotf_ax.set_facecolor(palette["card_bg"])
|
||||||
self.eotf_ax.set_xlim(0, 105)
|
self.eotf_ax.set_xlim(0, 105)
|
||||||
self.eotf_ax.set_ylim(0, 1.1)
|
self.eotf_ax.set_ylim(0, 1.1)
|
||||||
self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
self.eotf_ax.set_xlabel("灰阶 (%)", fontsize=10)
|
||||||
self.eotf_ax.set_ylabel("L_bar (归一化亮度)", fontsize=10)
|
self.eotf_ax.set_ylabel("L_bar (归一化亮度)", fontsize=10)
|
||||||
self.eotf_ax.grid(True, linestyle="--", alpha=0.3)
|
self.eotf_ax.grid(True, linestyle="--", alpha=0.3)
|
||||||
self.eotf_ax.tick_params(labelsize=9)
|
self.eotf_ax.tick_params(labelsize=9)
|
||||||
|
self.eotf_ax.tick_params(colors=palette["fg"])
|
||||||
|
for spine in self.eotf_ax.spines.values():
|
||||||
|
spine.set_color(palette["border"])
|
||||||
|
|
||||||
# 左侧提示
|
# 左侧提示
|
||||||
self.eotf_ax.text(
|
self.eotf_ax.text(
|
||||||
@@ -758,13 +811,13 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="center",
|
va="center",
|
||||||
fontsize=11,
|
fontsize=11,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.eotf_ax.transAxes,
|
transform=self.eotf_ax.transAxes,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=1",
|
boxstyle="round,pad=1",
|
||||||
facecolor="white",
|
facecolor=palette["card_bg"],
|
||||||
edgecolor="gray",
|
edgecolor=palette["border"],
|
||||||
alpha=0.8,
|
alpha=0.95,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -802,17 +855,17 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
# 表头样式
|
# 表头样式
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
cell = table[(0, i)]
|
cell = table[(0, i)]
|
||||||
cell.set_facecolor("#4472C4")
|
cell.set_facecolor(palette["primary"])
|
||||||
cell.set_text_props(weight="bold", color="white", fontsize=7)
|
cell.set_text_props(weight="bold", color=palette["select_fg"], fontsize=7)
|
||||||
|
|
||||||
# 数据行交替颜色
|
# 数据行交替颜色
|
||||||
for i in range(1, len(table_data)):
|
for i in range(1, len(table_data)):
|
||||||
for j in range(4):
|
for j in range(4):
|
||||||
cell = table[(i, j)]
|
cell = table[(i, j)]
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
cell.set_facecolor("#E7E6E6")
|
cell.set_facecolor(palette["surface_alt_bg"])
|
||||||
else:
|
else:
|
||||||
cell.set_facecolor("#FFFFFF")
|
cell.set_facecolor(palette["card_bg"])
|
||||||
|
|
||||||
# 底部说明
|
# 底部说明
|
||||||
self.eotf_table_ax.text(
|
self.eotf_table_ax.text(
|
||||||
@@ -825,17 +878,17 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
ha="center",
|
ha="center",
|
||||||
va="bottom",
|
va="bottom",
|
||||||
fontsize=7,
|
fontsize=7,
|
||||||
color="gray",
|
color=palette["muted_fg"],
|
||||||
transform=self.eotf_table_ax.transAxes,
|
transform=self.eotf_table_ax.transAxes,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=0.5",
|
boxstyle="round,pad=0.5",
|
||||||
facecolor="lightyellow",
|
facecolor=palette["surface_alt_bg"],
|
||||||
edgecolor="gray",
|
edgecolor=palette["border"],
|
||||||
alpha=0.8,
|
alpha=0.95,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.eotf_fig.suptitle("EOTF 曲线 + 数据表格", fontsize=12, y=0.98)
|
self.eotf_fig.suptitle("EOTF 曲线 + 数据表格", fontsize=12, y=0.98, color=palette["fg"])
|
||||||
self.eotf_canvas.draw()
|
self.eotf_canvas.draw()
|
||||||
|
|
||||||
# ========== 4. 清空色度图表 ==========
|
# ========== 4. 清空色度图表 ==========
|
||||||
@@ -843,8 +896,10 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
# 过期引用。因此清空时必须同样重建,并更新引用,否则清不干净。
|
# 过期引用。因此清空时必须同样重建,并更新引用,否则清不干净。
|
||||||
if hasattr(self, "cct_fig") and hasattr(self, "cct_canvas"):
|
if hasattr(self, "cct_fig") and hasattr(self, "cct_canvas"):
|
||||||
self.cct_fig.clear()
|
self.cct_fig.clear()
|
||||||
|
self.cct_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
|
||||||
self.cct_ax1 = self.cct_fig.add_subplot(211)
|
self.cct_ax1 = self.cct_fig.add_subplot(211)
|
||||||
|
self.cct_ax1.set_facecolor(palette["card_bg"])
|
||||||
self.cct_ax1.set_xlabel("灰阶 (%)", fontsize=9)
|
self.cct_ax1.set_xlabel("灰阶 (%)", fontsize=9)
|
||||||
self.cct_ax1.set_ylabel("CIE x", fontsize=9)
|
self.cct_ax1.set_ylabel("CIE x", fontsize=9)
|
||||||
self.cct_ax1.set_xlim(0, 105)
|
self.cct_ax1.set_xlim(0, 105)
|
||||||
@@ -853,6 +908,7 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
self.cct_ax1.tick_params(labelsize=8)
|
self.cct_ax1.tick_params(labelsize=8)
|
||||||
|
|
||||||
self.cct_ax2 = self.cct_fig.add_subplot(212)
|
self.cct_ax2 = self.cct_fig.add_subplot(212)
|
||||||
|
self.cct_ax2.set_facecolor(palette["card_bg"])
|
||||||
self.cct_ax2.set_xlabel("灰阶 (%)", fontsize=9)
|
self.cct_ax2.set_xlabel("灰阶 (%)", fontsize=9)
|
||||||
self.cct_ax2.set_ylabel("CIE y", fontsize=9)
|
self.cct_ax2.set_ylabel("CIE y", fontsize=9)
|
||||||
self.cct_ax2.set_xlim(0, 105)
|
self.cct_ax2.set_xlim(0, 105)
|
||||||
@@ -860,7 +916,7 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
self.cct_ax2.grid(True, linestyle="--", alpha=0.3)
|
self.cct_ax2.grid(True, linestyle="--", alpha=0.3)
|
||||||
self.cct_ax2.tick_params(labelsize=8)
|
self.cct_ax2.tick_params(labelsize=8)
|
||||||
|
|
||||||
self.cct_fig.suptitle("色度一致性测试", fontsize=12, y=0.985)
|
self.cct_fig.suptitle("色度一致性测试", fontsize=12, y=0.985, color=palette["fg"])
|
||||||
self.cct_fig.subplots_adjust(
|
self.cct_fig.subplots_adjust(
|
||||||
left=0.12,
|
left=0.12,
|
||||||
right=0.88,
|
right=0.88,
|
||||||
@@ -873,11 +929,13 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
# ========== 5. 清空对比度图表 ==========
|
# ========== 5. 清空对比度图表 ==========
|
||||||
if hasattr(self, "contrast_ax"):
|
if hasattr(self, "contrast_ax"):
|
||||||
self.contrast_ax.clear()
|
self.contrast_ax.clear()
|
||||||
|
self.contrast_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
self.contrast_ax.set_facecolor(palette["card_bg"])
|
||||||
self.contrast_ax.set_xlim(0, 1)
|
self.contrast_ax.set_xlim(0, 1)
|
||||||
self.contrast_ax.set_ylim(0, 1)
|
self.contrast_ax.set_ylim(0, 1)
|
||||||
self.contrast_ax.axis("off")
|
self.contrast_ax.axis("off")
|
||||||
|
|
||||||
self.contrast_fig.suptitle("对比度测试", fontsize=12, y=0.985)
|
self.contrast_fig.suptitle("对比度测试", fontsize=12, y=0.985, color=palette["fg"])
|
||||||
|
|
||||||
# 重置布局
|
# 重置布局
|
||||||
self.contrast_fig.subplots_adjust(
|
self.contrast_fig.subplots_adjust(
|
||||||
@@ -892,12 +950,14 @@ def clear_chart(self: "PQAutomationApp"):
|
|||||||
# ========== 6. 清空色准图表 ==========
|
# ========== 6. 清空色准图表 ==========
|
||||||
if hasattr(self, "accuracy_ax"):
|
if hasattr(self, "accuracy_ax"):
|
||||||
self.accuracy_ax.clear()
|
self.accuracy_ax.clear()
|
||||||
|
self.accuracy_fig.patch.set_facecolor(palette["bg"])
|
||||||
|
self.accuracy_ax.set_facecolor(palette["card_bg"])
|
||||||
self.accuracy_ax.set_xlim(0, 1)
|
self.accuracy_ax.set_xlim(0, 1)
|
||||||
self.accuracy_ax.set_ylim(0, 1)
|
self.accuracy_ax.set_ylim(0, 1)
|
||||||
self.accuracy_ax.axis("off")
|
self.accuracy_ax.axis("off")
|
||||||
|
|
||||||
# 标题
|
# 标题
|
||||||
self.accuracy_fig.suptitle("色准测试", fontsize=12, y=0.985)
|
self.accuracy_fig.suptitle("色准测试", fontsize=12, y=0.985, color=palette["fg"])
|
||||||
|
|
||||||
# 重置布局
|
# 重置布局
|
||||||
self.accuracy_fig.subplots_adjust(
|
self.accuracy_fig.subplots_adjust(
|
||||||
|
|||||||
@@ -600,7 +600,6 @@ def create_connection_content(self: "PQAutomationApp"):
|
|||||||
com_frame, width=15, height=15, bg="gray", highlightthickness=0
|
com_frame, width=15, height=15, bg="gray", highlightthickness=0
|
||||||
)
|
)
|
||||||
self.ucd_status_indicator.grid(row=0, column=2, padx=(10, 20))
|
self.ucd_status_indicator.grid(row=0, column=2, padx=(10, 20))
|
||||||
self.ucd_status_indicator.config(bg="gray")
|
|
||||||
|
|
||||||
# 添加按钮框架
|
# 添加按钮框架
|
||||||
button_frame = ttk.Frame(com_frame)
|
button_frame = ttk.Frame(com_frame)
|
||||||
@@ -669,7 +668,8 @@ def create_connection_content(self: "PQAutomationApp"):
|
|||||||
com_frame, width=15, height=15, bg="gray", highlightthickness=0
|
com_frame, width=15, height=15, bg="gray", highlightthickness=0
|
||||||
)
|
)
|
||||||
self.ca_status_indicator.grid(row=1, column=2, padx=(10, 20))
|
self.ca_status_indicator.grid(row=1, column=2, padx=(10, 20))
|
||||||
self.ca_status_indicator.config(bg="gray")
|
|
||||||
|
self.refresh_connection_indicators()
|
||||||
|
|
||||||
# 添加CA通道设置
|
# 添加CA通道设置
|
||||||
ttk.Label(com_frame, text="CA通道:").grid(
|
ttk.Label(com_frame, text="CA通道:").grid(
|
||||||
@@ -808,6 +808,11 @@ def _on_toggle_theme(self: "PQAutomationApp") -> None:
|
|||||||
toggle_theme()
|
toggle_theme()
|
||||||
# apply_modern_styles()
|
# apply_modern_styles()
|
||||||
_refresh_theme_toggle_label(self)
|
_refresh_theme_toggle_label(self)
|
||||||
|
if hasattr(self, "refresh_connection_indicators"):
|
||||||
|
try:
|
||||||
|
self.refresh_connection_indicators()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
if hasattr(self, "apply_result_chart_theme"):
|
if hasattr(self, "apply_result_chart_theme"):
|
||||||
try:
|
try:
|
||||||
self.apply_result_chart_theme()
|
self.apply_result_chart_theme()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import time
|
|||||||
import os
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
import traceback
|
import traceback
|
||||||
|
import matplotlib
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from app_version import APP_NAME, APP_VERSION, get_app_title
|
from app_version import APP_NAME, APP_VERSION, get_app_title
|
||||||
from drivers.UCD323_Function import UCDController
|
from drivers.UCD323_Function import UCDController
|
||||||
@@ -62,7 +63,6 @@ from app.runner.test_runner import TestRunnerMixin
|
|||||||
plt.rcParams["font.family"] = ["sans-serif"]
|
plt.rcParams["font.family"] = ["sans-serif"]
|
||||||
plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
|
plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
|
||||||
|
|
||||||
|
|
||||||
class PQAutomationApp(
|
class PQAutomationApp(
|
||||||
ConfigIOMixin,
|
ConfigIOMixin,
|
||||||
ChartFrameMixin,
|
ChartFrameMixin,
|
||||||
@@ -431,6 +431,11 @@ class PQAutomationApp(
|
|||||||
|
|
||||||
# 更新测试项目和侧边栏
|
# 更新测试项目和侧边栏
|
||||||
self.update_test_items()
|
self.update_test_items()
|
||||||
|
if hasattr(self, "refresh_connection_indicators"):
|
||||||
|
try:
|
||||||
|
self.refresh_connection_indicators()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
self.update_sidebar_selection()
|
self.update_sidebar_selection()
|
||||||
self.on_test_type_change()
|
self.on_test_type_change()
|
||||||
self._switch_signal_format_tabs(test_type)
|
self._switch_signal_format_tabs(test_type)
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
{
|
{
|
||||||
"current_test_type": "sdr_movie",
|
"current_test_type": "screen_module",
|
||||||
"test_types": {
|
"test_types": {
|
||||||
"screen_module": {
|
"screen_module": {
|
||||||
"name": "屏模组性能测试",
|
"name": "屏模组性能测试",
|
||||||
"test_items": [
|
"test_items": [
|
||||||
"gamma"
|
"gamut",
|
||||||
|
"gamma",
|
||||||
|
"cct",
|
||||||
|
"contrast"
|
||||||
],
|
],
|
||||||
"timing": "DMT 1920x 1080 @ 60Hz",
|
"timing": "DMT 1920x 1080 @ 60Hz",
|
||||||
"data_range": "Full",
|
"data_range": "Full",
|
||||||
@@ -51,7 +54,7 @@
|
|||||||
"y_ideal": 0.329,
|
"y_ideal": 0.329,
|
||||||
"y_tolerance": 0.003
|
"y_tolerance": 0.003
|
||||||
},
|
},
|
||||||
"gamut_reference": "BT.709"
|
"gamut_reference": "BT.601"
|
||||||
},
|
},
|
||||||
"hdr_movie": {
|
"hdr_movie": {
|
||||||
"name": "HDR Movie测试",
|
"name": "HDR Movie测试",
|
||||||
|
|||||||
Reference in New Issue
Block a user