继续优化深色模式显示
This commit is contained in:
@@ -2,6 +2,21 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
_EXPORT_BG_COLOR = "#FFFFFF"
|
||||||
|
|
||||||
|
|
||||||
|
def _save_with_light_background(fig, path, *, dpi=300, bbox_inches=None):
|
||||||
|
"""导出统一浅色背景,避免深色主题下图片背景变暗。"""
|
||||||
|
kwargs = {
|
||||||
|
"dpi": dpi,
|
||||||
|
"facecolor": _EXPORT_BG_COLOR,
|
||||||
|
"edgecolor": _EXPORT_BG_COLOR,
|
||||||
|
}
|
||||||
|
if bbox_inches is not None:
|
||||||
|
kwargs["bbox_inches"] = bbox_inches
|
||||||
|
fig.savefig(path, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def _gamut_refs_for_type(test_type):
|
def _gamut_refs_for_type(test_type):
|
||||||
"""按测试类型返回需要导出的参考色域列表。"""
|
"""按测试类型返回需要导出的参考色域列表。"""
|
||||||
if test_type == "sdr_movie":
|
if test_type == "sdr_movie":
|
||||||
@@ -70,7 +85,7 @@ def save_result_images(result_dir, current_test_type, selected_items,
|
|||||||
continue
|
continue
|
||||||
per_ref_name = f"色域测试结果_{ref}.png"
|
per_ref_name = f"色域测试结果_{ref}.png"
|
||||||
path = os.path.join(result_dir, per_ref_name)
|
path = os.path.join(result_dir, per_ref_name)
|
||||||
fig.savefig(path, dpi=300)
|
_save_with_light_background(fig, path, dpi=300)
|
||||||
log(f"已保存: {per_ref_name}")
|
log(f"已保存: {per_ref_name}")
|
||||||
finally:
|
finally:
|
||||||
ref_var.set(original_ref)
|
ref_var.set(original_ref)
|
||||||
@@ -82,7 +97,7 @@ def save_result_images(result_dir, current_test_type, selected_items,
|
|||||||
continue
|
continue
|
||||||
path = os.path.join(result_dir, filename)
|
path = os.path.join(result_dir, filename)
|
||||||
if default_bbox:
|
if default_bbox:
|
||||||
fig.savefig(path, dpi=300)
|
_save_with_light_background(fig, path, dpi=300)
|
||||||
else:
|
else:
|
||||||
fig.savefig(path, dpi=300, bbox_inches="tight")
|
_save_with_light_background(fig, path, dpi=300, bbox_inches="tight")
|
||||||
log(f"已保存: {filename}")
|
log(f"已保存: {filename}")
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ def _xy_to_uv(x: float, y: float):
|
|||||||
# 子图:左侧 Calman 风格面板
|
# 子图:左侧 Calman 风格面板
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def _draw_left_panel(ax, color_patches, delta_e_values, font_scale=1.0):
|
def _draw_left_panel(ax, color_patches, delta_e_values, font_scale=1.0, dark_mode=False):
|
||||||
"""左侧仅保留大条形图。"""
|
"""左侧仅保留大条形图。"""
|
||||||
ax.clear()
|
ax.clear()
|
||||||
|
|
||||||
@@ -98,19 +98,23 @@ def _draw_left_panel(ax, color_patches, delta_e_values, font_scale=1.0):
|
|||||||
zorder=3,
|
zorder=3,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
text_color = "#F3F5F7" if dark_mode else "#111111"
|
||||||
|
bg_color = "#0F1115" if dark_mode else "#FFFFFF"
|
||||||
|
spine_color = "#8C8F94" if dark_mode else "#9A9A9A"
|
||||||
|
|
||||||
ax.set_yticks(y_pos)
|
ax.set_yticks(y_pos)
|
||||||
ax.set_yticklabels(color_patches, fontsize=max(5, 7 * font_scale))
|
ax.set_yticklabels(color_patches, fontsize=max(5, 7 * font_scale), color=text_color)
|
||||||
ax.invert_yaxis()
|
ax.invert_yaxis()
|
||||||
|
|
||||||
x_max = max(15.0, max(delta_e_values) * 1.15)
|
x_max = max(15.0, max(delta_e_values) * 1.15)
|
||||||
ax.set_xlim(0, x_max)
|
ax.set_xlim(0, x_max)
|
||||||
ax.tick_params(axis="x", labelsize=max(6, 8 * font_scale))
|
ax.tick_params(axis="x", labelsize=max(6, 8 * font_scale), colors=text_color)
|
||||||
ax.grid(axis="x", linestyle="-", linewidth=0.6, alpha=0.3, zorder=0)
|
ax.grid(axis="x", linestyle="-", linewidth=0.6, alpha=0.3, zorder=0)
|
||||||
ax.grid(axis="y", linestyle=":", linewidth=0.35, alpha=0.15, zorder=0)
|
ax.grid(axis="y", linestyle=":", linewidth=0.35, alpha=0.15, zorder=0)
|
||||||
|
|
||||||
ax.set_facecolor("#FFFFFF")
|
ax.set_facecolor(bg_color)
|
||||||
for spine in ax.spines.values():
|
for spine in ax.spines.values():
|
||||||
spine.set_color("#9A9A9A")
|
spine.set_color(spine_color)
|
||||||
spine.set_linewidth(0.9)
|
spine.set_linewidth(0.9)
|
||||||
|
|
||||||
|
|
||||||
@@ -118,7 +122,7 @@ def _draw_left_panel(ax, color_patches, delta_e_values, font_scale=1.0):
|
|||||||
# 子图:CIE 1976 u'v' 色度图(目标 vs 实测)
|
# 子图:CIE 1976 u'v' 色度图(目标 vs 实测)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0):
|
def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0, dark_mode=False):
|
||||||
"""绘制 CIE 1976 u'v' 上的色准对比。"""
|
"""绘制 CIE 1976 u'v' 上的色准对比。"""
|
||||||
ax.clear()
|
ax.clear()
|
||||||
try:
|
try:
|
||||||
@@ -135,15 +139,23 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0)
|
|||||||
ax.set_xlim(0.0, 0.65)
|
ax.set_xlim(0.0, 0.65)
|
||||||
ax.set_ylim(0.0, 0.60)
|
ax.set_ylim(0.0, 0.60)
|
||||||
|
|
||||||
ax.set_facecolor("#000")
|
text_color = "#F3F5F7" if dark_mode else "#111111"
|
||||||
|
sub_text_color = "#D3D7DD" if dark_mode else "#222222"
|
||||||
|
tick_color = "#D3D7DD" if dark_mode else "#222222"
|
||||||
|
legend_label_color = "#FFF" if dark_mode else "#111"
|
||||||
|
legend_bg = "#111" if dark_mode else "#FFFFFF"
|
||||||
|
legend_edge = "#FFF" if dark_mode else "#333"
|
||||||
|
outer_edge = "#FFFFFF" if dark_mode else "#333333"
|
||||||
|
|
||||||
|
ax.set_facecolor("#000" if dark_mode else "#FFFFFF")
|
||||||
ax.set_aspect("equal", adjustable="box")
|
ax.set_aspect("equal", adjustable="box")
|
||||||
ax.set_title("CIE 1976 u'v'", fontsize=max(8, 11 * font_scale), fontweight="bold",
|
ax.set_title("CIE 1976 u'v'", fontsize=max(8, 11 * font_scale), fontweight="bold",
|
||||||
color="#111", pad=4)
|
color=text_color, pad=4)
|
||||||
ax.set_xlabel("u'", fontsize=max(7, 9 * font_scale), color="#222", labelpad=1)
|
ax.set_xlabel("u'", fontsize=max(7, 9 * font_scale), color=sub_text_color, labelpad=1)
|
||||||
ax.set_ylabel("v'", fontsize=max(7, 9 * font_scale), color="#222", labelpad=1)
|
ax.set_ylabel("v'", fontsize=max(7, 9 * font_scale), color=sub_text_color, labelpad=1)
|
||||||
ax.tick_params(axis="both", labelsize=max(6, 8 * font_scale), colors="#222")
|
ax.tick_params(axis="both", labelsize=max(6, 8 * font_scale), colors=tick_color)
|
||||||
for sp in ax.spines.values():
|
for sp in ax.spines.values():
|
||||||
sp.set_color("#666")
|
sp.set_color(outer_edge)
|
||||||
sp.set_linewidth(0.9)
|
sp.set_linewidth(0.9)
|
||||||
|
|
||||||
for name, meas in zip(color_patches, measurements):
|
for name, meas in zip(color_patches, measurements):
|
||||||
@@ -164,14 +176,14 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0)
|
|||||||
ax.scatter(
|
ax.scatter(
|
||||||
[s_u], [s_v],
|
[s_u], [s_v],
|
||||||
s=56, marker="s",
|
s=56, marker="s",
|
||||||
facecolors="none", edgecolors="#FFFFFF",
|
facecolors="none", edgecolors=outer_edge,
|
||||||
linewidths=1.25, zorder=18,
|
linewidths=1.25, zorder=18,
|
||||||
)
|
)
|
||||||
# 实测点:白色外圈 + 内层圆点
|
# 实测点:白色外圈 + 内层圆点
|
||||||
ax.scatter(
|
ax.scatter(
|
||||||
[m_u], [m_v],
|
[m_u], [m_v],
|
||||||
s=52, marker="o",
|
s=52, marker="o",
|
||||||
facecolors="none", edgecolors="#FFFFFF",
|
facecolors="none", edgecolors=outer_edge,
|
||||||
linewidths=1.0, zorder=19,
|
linewidths=1.0, zorder=19,
|
||||||
)
|
)
|
||||||
ax.scatter(
|
ax.scatter(
|
||||||
@@ -183,7 +195,7 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0)
|
|||||||
|
|
||||||
legend_handles = [
|
legend_handles = [
|
||||||
Line2D([0], [0], marker="s", linestyle="none",
|
Line2D([0], [0], marker="s", linestyle="none",
|
||||||
markerfacecolor="#CCCCCC", markeredgecolor="#FFFFFF",
|
markerfacecolor="#CCCCCC", markeredgecolor=outer_edge,
|
||||||
markersize=7, label="目标 (Target)"),
|
markersize=7, label="目标 (Target)"),
|
||||||
Line2D([0], [0], marker="o", linestyle="none",
|
Line2D([0], [0], marker="o", linestyle="none",
|
||||||
markerfacecolor="#CCCCCC", markeredgecolor="#000000",
|
markerfacecolor="#CCCCCC", markeredgecolor="#000000",
|
||||||
@@ -192,15 +204,15 @@ def _draw_uv_diagram(ax, color_patches, measurements, standards, font_scale=1.0)
|
|||||||
leg = ax.legend(
|
leg = ax.legend(
|
||||||
handles=legend_handles,
|
handles=legend_handles,
|
||||||
loc="lower right", fontsize=max(6, 8 * font_scale),
|
loc="lower right", fontsize=max(6, 8 * font_scale),
|
||||||
framealpha=0.88, labelcolor="#FFF",
|
framealpha=0.88, labelcolor=legend_label_color,
|
||||||
)
|
)
|
||||||
if leg is not None:
|
if leg is not None:
|
||||||
leg.get_frame().set_facecolor("#111")
|
leg.get_frame().set_facecolor(legend_bg)
|
||||||
leg.get_frame().set_edgecolor("#FFF")
|
leg.get_frame().set_edgecolor(legend_edge)
|
||||||
leg.set_zorder(50)
|
leg.set_zorder(50)
|
||||||
|
|
||||||
|
|
||||||
def _draw_result_judgement(ax, accuracy_data, font_scale=1.0):
|
def _draw_result_judgement(ax, accuracy_data, font_scale=1.0, dark_mode=False):
|
||||||
"""底部结果条"""
|
"""底部结果条"""
|
||||||
ax.clear()
|
ax.clear()
|
||||||
ax.set_xlim(0, 1)
|
ax.set_xlim(0, 1)
|
||||||
@@ -210,24 +222,28 @@ def _draw_result_judgement(ax, accuracy_data, font_scale=1.0):
|
|||||||
avg = accuracy_data.get("avg_delta_e", 0.0)
|
avg = accuracy_data.get("avg_delta_e", 0.0)
|
||||||
mx = accuracy_data.get("max_delta_e", 0.0)
|
mx = accuracy_data.get("max_delta_e", 0.0)
|
||||||
|
|
||||||
|
panel_bg = "#1A1E24" if dark_mode else "#FFFFFF"
|
||||||
|
panel_edge = "#4A5058" if dark_mode else "#C6C6C6"
|
||||||
|
text_color = "#F3F5F7" if dark_mode else "#111111"
|
||||||
|
|
||||||
ax.add_patch(Rectangle(
|
ax.add_patch(Rectangle(
|
||||||
(0.0, 0.10), 1.0, 0.80,
|
(0.0, 0.10), 1.0, 0.80,
|
||||||
transform=ax.transAxes,
|
transform=ax.transAxes,
|
||||||
facecolor="#FFFFFF", edgecolor="#C6C6C6", linewidth=1.0,
|
facecolor=panel_bg, edgecolor=panel_edge, linewidth=1.0,
|
||||||
))
|
))
|
||||||
|
|
||||||
ax.text(
|
ax.text(
|
||||||
0.03, 0.50,
|
0.03, 0.50,
|
||||||
f"Avg dE2000: {avg:.2f}",
|
f"Avg dE2000: {avg:.2f}",
|
||||||
ha="left", va="center",
|
ha="left", va="center",
|
||||||
fontsize=max(11, 20 * font_scale), fontweight="normal", color="#111111",
|
fontsize=max(11, 20 * font_scale), fontweight="normal", color=text_color,
|
||||||
transform=ax.transAxes,
|
transform=ax.transAxes,
|
||||||
)
|
)
|
||||||
ax.text(
|
ax.text(
|
||||||
0.52, 0.50,
|
0.52, 0.50,
|
||||||
f"Max dE2000: {mx:.2f}",
|
f"Max dE2000: {mx:.2f}",
|
||||||
ha="left", va="center",
|
ha="left", va="center",
|
||||||
fontsize=max(11, 20 * font_scale), fontweight="normal", color="#111111",
|
fontsize=max(11, 20 * font_scale), fontweight="normal", color=text_color,
|
||||||
transform=ax.transAxes,
|
transform=ax.transAxes,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -242,6 +258,14 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
|
|||||||
fig = self.accuracy_fig
|
fig = self.accuracy_fig
|
||||||
fig.clear()
|
fig.clear()
|
||||||
|
|
||||||
|
try:
|
||||||
|
from app.views.theme_manager import is_dark
|
||||||
|
dark_mode = is_dark()
|
||||||
|
except Exception:
|
||||||
|
dark_mode = False
|
||||||
|
|
||||||
|
fig.patch.set_facecolor("#1B1F24" if dark_mode else "#FFFFFF")
|
||||||
|
|
||||||
# 根据当前画布像素尺寸动态缩放字体,避免窗口缩小时文字挤压重叠。
|
# 根据当前画布像素尺寸动态缩放字体,避免窗口缩小时文字挤压重叠。
|
||||||
font_scale = 1.0
|
font_scale = 1.0
|
||||||
try:
|
try:
|
||||||
@@ -271,12 +295,13 @@ 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="#111",
|
color=title_color,
|
||||||
)
|
)
|
||||||
|
|
||||||
gs = fig.add_gridspec(
|
gs = fig.add_gridspec(
|
||||||
@@ -295,7 +320,13 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
|
|||||||
# 兼容外部对 self.accuracy_ax 的引用
|
# 兼容外部对 self.accuracy_ax 的引用
|
||||||
self.accuracy_ax = ax_judge
|
self.accuracy_ax = ax_judge
|
||||||
|
|
||||||
_draw_left_panel(ax_left, color_patches, delta_e_values, font_scale=font_scale)
|
_draw_left_panel(
|
||||||
|
ax_left,
|
||||||
|
color_patches,
|
||||||
|
delta_e_values,
|
||||||
|
font_scale=font_scale,
|
||||||
|
dark_mode=dark_mode,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
standards = get_accuracy_color_standards(test_type)
|
standards = get_accuracy_color_standards(test_type)
|
||||||
@@ -308,8 +339,14 @@ def plot_accuracy(self: "PQAutomationApp", accuracy_data, test_type):
|
|||||||
measurements,
|
measurements,
|
||||||
standards,
|
standards,
|
||||||
font_scale=font_scale,
|
font_scale=font_scale,
|
||||||
|
dark_mode=dark_mode,
|
||||||
|
)
|
||||||
|
_draw_result_judgement(
|
||||||
|
ax_judge,
|
||||||
|
accuracy_data,
|
||||||
|
font_scale=font_scale,
|
||||||
|
dark_mode=dark_mode,
|
||||||
)
|
)
|
||||||
_draw_result_judgement(ax_judge, accuracy_data, font_scale=font_scale)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.update_accuracy_result_table(accuracy_data, standards)
|
self.update_accuracy_result_table(accuracy_data, standards)
|
||||||
|
|||||||
@@ -148,35 +148,41 @@ def _draw_measured_triangle(ax, vertices, *, uv_space=False):
|
|||||||
# )
|
# )
|
||||||
|
|
||||||
|
|
||||||
def _draw_coverage_box(ax, x_pos, y_pos, current_ref, coverage):
|
def _draw_coverage_box(ax, x_pos, y_pos, current_ref, coverage, *, dark_mode):
|
||||||
|
text_color = "#FFF" if dark_mode else "#111"
|
||||||
|
box_face = "#111" if dark_mode else "#FFFFFF"
|
||||||
|
box_edge = "#FFF" if dark_mode else "#333"
|
||||||
ax.text(
|
ax.text(
|
||||||
x_pos, y_pos,
|
x_pos, y_pos,
|
||||||
f"{current_ref}\n覆盖率: {coverage:.1f}%",
|
f"{current_ref}\n覆盖率: {coverage:.1f}%",
|
||||||
ha="right", va="bottom",
|
ha="right", va="bottom",
|
||||||
fontsize=11, fontweight="bold",
|
fontsize=11, fontweight="bold",
|
||||||
color="#FFF",
|
color=text_color,
|
||||||
bbox=dict(
|
bbox=dict(
|
||||||
boxstyle="round,pad=0.38",
|
boxstyle="round,pad=0.38",
|
||||||
facecolor="#111",
|
facecolor=box_face,
|
||||||
edgecolor="#FFF",
|
edgecolor=box_edge,
|
||||||
linewidth=1.7,
|
linewidth=1.7,
|
||||||
alpha=0.98,
|
alpha=0.98,
|
||||||
),
|
),
|
||||||
zorder=30,
|
zorder=30,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _style_axes(ax, *, title, xlabel, ylabel, xlim, ylim):
|
def _style_axes(ax, *, title, xlabel, ylabel, xlim, ylim, dark_mode):
|
||||||
ax.set_facecolor("#000")
|
text = "#F4F6F8" if dark_mode else "#111"
|
||||||
ax.set_title(title, fontsize=12, fontweight="bold", color="#FFF", pad=8)
|
grid = "#444" if dark_mode else "#B8BDC3"
|
||||||
ax.set_xlabel(xlabel, fontsize=10, color="#FFF")
|
spine_color = "#888" if dark_mode else "#666"
|
||||||
ax.set_ylabel(ylabel, fontsize=10, color="#FFF")
|
ax.set_facecolor("#000" if dark_mode else "#FFFFFF")
|
||||||
|
ax.set_title(title, fontsize=12, fontweight="bold", color=text, pad=8)
|
||||||
|
ax.set_xlabel(xlabel, 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="datalim")
|
||||||
ax.grid(True, linestyle=":", linewidth=0.7, color="#444", alpha=0.32)
|
ax.grid(True, linestyle=":", linewidth=0.7, color=grid, alpha=0.32)
|
||||||
ax.tick_params(axis="both", labelsize=9, colors="#FFF")
|
ax.tick_params(axis="both", labelsize=9, colors=text)
|
||||||
for spine in ax.spines.values():
|
for spine in ax.spines.values():
|
||||||
spine.set_color("#888")
|
spine.set_color(spine_color)
|
||||||
spine.set_linewidth(0.8)
|
spine.set_linewidth(0.8)
|
||||||
ax.set_clip_on(False)
|
ax.set_clip_on(False)
|
||||||
|
|
||||||
@@ -201,13 +207,19 @@ def _blit_background(ax, background, bbox):
|
|||||||
def plot_gamut(self: "PQAutomationApp", results, coverage, test_type):
|
def plot_gamut(self: "PQAutomationApp", results, coverage, test_type):
|
||||||
"""绘制色域图(图像层 + 框架层分离架构)。"""
|
"""绘制色域图(图像层 + 框架层分离架构)。"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
from app.views.theme_manager import is_dark
|
||||||
|
dark_mode = is_dark()
|
||||||
|
except Exception:
|
||||||
|
dark_mode = False
|
||||||
|
|
||||||
ax_xy = self.gamut_ax_xy
|
ax_xy = self.gamut_ax_xy
|
||||||
ax_uv = self.gamut_ax_uv
|
ax_uv = self.gamut_ax_uv
|
||||||
|
|
||||||
ax_xy.clear()
|
ax_xy.clear()
|
||||||
ax_uv.clear()
|
ax_uv.clear()
|
||||||
# 全局黑色背景
|
# 全局背景跟随浅/深色主题
|
||||||
self.gamut_fig.patch.set_facecolor("#000")
|
self.gamut_fig.patch.set_facecolor("#0D1014" if dark_mode else "#FFFFFF")
|
||||||
|
|
||||||
# ========== 读取用户选择的参考标准 ==========
|
# ========== 读取用户选择的参考标准 ==========
|
||||||
if test_type == "screen_module":
|
if test_type == "screen_module":
|
||||||
@@ -265,6 +277,7 @@ def plot_gamut(self: "PQAutomationApp", results, coverage, test_type):
|
|||||||
xlabel="x", ylabel="y",
|
xlabel="x", ylabel="y",
|
||||||
xlim=(bbox_xy[0], bbox_xy[1]),
|
xlim=(bbox_xy[0], bbox_xy[1]),
|
||||||
ylim=(bbox_xy[2], bbox_xy[3]),
|
ylim=(bbox_xy[2], bbox_xy[3]),
|
||||||
|
dark_mode=dark_mode,
|
||||||
)
|
)
|
||||||
|
|
||||||
for ref_name in other_refs:
|
for ref_name in other_refs:
|
||||||
@@ -289,7 +302,8 @@ def plot_gamut(self: "PQAutomationApp", results, coverage, test_type):
|
|||||||
_draw_measured_triangle(ax_xy, measured_xy, uv_space=False)
|
_draw_measured_triangle(ax_xy, measured_xy, uv_space=False)
|
||||||
|
|
||||||
_draw_coverage_box(
|
_draw_coverage_box(
|
||||||
ax_xy, bbox_xy[1] - 0.02, bbox_xy[2] + 0.02, current_ref, xy_coverage
|
ax_xy, bbox_xy[1] - 0.02, bbox_xy[2] + 0.02, current_ref, xy_coverage,
|
||||||
|
dark_mode=dark_mode,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 暗化三角形外部区域(黑色半透明遮罩)
|
# 暗化三角形外部区域(黑色半透明遮罩)
|
||||||
@@ -303,18 +317,19 @@ def plot_gamut(self: "PQAutomationApp", results, coverage, test_type):
|
|||||||
codes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY]
|
codes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY]
|
||||||
codes += [Path.MOVETO] + [Path.LINETO]*2 + [Path.CLOSEPOLY]
|
codes += [Path.MOVETO] + [Path.LINETO]*2 + [Path.CLOSEPOLY]
|
||||||
path = Path(verts, codes)
|
path = Path(verts, codes)
|
||||||
patch = PathPatch(path, facecolor=(0,0,0,0.65), lw=0, zorder=7)
|
mask_face = (0, 0, 0, 0.65) if dark_mode else (1, 1, 1, 0.50)
|
||||||
|
patch = PathPatch(path, facecolor=mask_face, lw=0, zorder=7)
|
||||||
ax_xy.add_patch(patch)
|
ax_xy.add_patch(patch)
|
||||||
|
|
||||||
legend = ax_xy.legend(
|
legend = ax_xy.legend(
|
||||||
loc="upper right", fontsize=8.5,
|
loc="upper right", fontsize=8.5,
|
||||||
framealpha=0.0, edgecolor="#000", fancybox=True,
|
framealpha=0.0, edgecolor="#000", fancybox=True,
|
||||||
labelcolor="#FFF"
|
labelcolor="#FFF" if dark_mode else "#111"
|
||||||
)
|
)
|
||||||
legend.set_zorder(200)
|
legend.set_zorder(200)
|
||||||
legend.get_frame().set_facecolor("#000")
|
legend.get_frame().set_facecolor("#000" if dark_mode else "#FFFFFF")
|
||||||
legend.get_frame().set_alpha(0.5)
|
legend.get_frame().set_alpha(0.5 if dark_mode else 0.78)
|
||||||
legend.get_frame().set_edgecolor("#FFF")
|
legend.get_frame().set_edgecolor("#FFF" if dark_mode else "#333")
|
||||||
ax_xy.add_artist(legend)
|
ax_xy.add_artist(legend)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -334,6 +349,7 @@ def plot_gamut(self: "PQAutomationApp", results, coverage, test_type):
|
|||||||
xlabel="u'", ylabel="v'",
|
xlabel="u'", ylabel="v'",
|
||||||
xlim=(bbox_uv[0], bbox_uv[1]),
|
xlim=(bbox_uv[0], bbox_uv[1]),
|
||||||
ylim=(bbox_uv[2], bbox_uv[3]),
|
ylim=(bbox_uv[2], bbox_uv[3]),
|
||||||
|
dark_mode=dark_mode,
|
||||||
)
|
)
|
||||||
|
|
||||||
measured_uv = None
|
measured_uv = None
|
||||||
@@ -367,7 +383,8 @@ def plot_gamut(self: "PQAutomationApp", results, coverage, test_type):
|
|||||||
_draw_measured_triangle(ax_uv, measured_uv, uv_space=True)
|
_draw_measured_triangle(ax_uv, measured_uv, uv_space=True)
|
||||||
|
|
||||||
_draw_coverage_box(
|
_draw_coverage_box(
|
||||||
ax_uv, bbox_uv[1] - 0.015, bbox_uv[2] + 0.015, current_ref, uv_coverage
|
ax_uv, bbox_uv[1] - 0.015, bbox_uv[2] + 0.015, current_ref, uv_coverage,
|
||||||
|
dark_mode=dark_mode,
|
||||||
)
|
)
|
||||||
|
|
||||||
u0, u1 = bbox_uv[0], bbox_uv[1]
|
u0, u1 = bbox_uv[0], bbox_uv[1]
|
||||||
@@ -379,18 +396,19 @@ def plot_gamut(self: "PQAutomationApp", results, coverage, test_type):
|
|||||||
codes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY]
|
codes = [Path.MOVETO] + [Path.LINETO]*3 + [Path.CLOSEPOLY]
|
||||||
codes += [Path.MOVETO] + [Path.LINETO]*2 + [Path.CLOSEPOLY]
|
codes += [Path.MOVETO] + [Path.LINETO]*2 + [Path.CLOSEPOLY]
|
||||||
path = Path(verts, codes)
|
path = Path(verts, codes)
|
||||||
patch = PathPatch(path, facecolor=(0,0,0,0.65), lw=0, zorder=7)
|
mask_face = (0, 0, 0, 0.65) if dark_mode else (1, 1, 1, 0.50)
|
||||||
|
patch = PathPatch(path, facecolor=mask_face, lw=0, zorder=7)
|
||||||
ax_uv.add_patch(patch)
|
ax_uv.add_patch(patch)
|
||||||
|
|
||||||
legend_uv = ax_uv.legend(
|
legend_uv = ax_uv.legend(
|
||||||
loc="upper right", fontsize=8.5,
|
loc="upper right", fontsize=8.5,
|
||||||
framealpha=0.0, edgecolor="#000", fancybox=True,
|
framealpha=0.0, edgecolor="#000", fancybox=True,
|
||||||
labelcolor="#FFF"
|
labelcolor="#FFF" if dark_mode else "#111"
|
||||||
)
|
)
|
||||||
legend_uv.set_zorder(200)
|
legend_uv.set_zorder(200)
|
||||||
legend_uv.get_frame().set_facecolor("#000")
|
legend_uv.get_frame().set_facecolor("#000" if dark_mode else "#FFFFFF")
|
||||||
legend_uv.get_frame().set_alpha(0.72)
|
legend_uv.get_frame().set_alpha(0.72 if dark_mode else 0.82)
|
||||||
legend_uv.get_frame().set_edgecolor("#FFF")
|
legend_uv.get_frame().set_edgecolor("#FFF" if dark_mode else "#333")
|
||||||
ax_uv.add_artist(legend_uv)
|
ax_uv.add_artist(legend_uv)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -16,6 +16,45 @@ if TYPE_CHECKING:
|
|||||||
from pqAutomationApp import PQAutomationApp
|
from pqAutomationApp import PQAutomationApp
|
||||||
|
|
||||||
|
|
||||||
|
def _result_bg_color() -> str:
|
||||||
|
"""根据当前主题返回结果图背景色。"""
|
||||||
|
try:
|
||||||
|
from app.views.theme_manager import is_dark
|
||||||
|
return "#1B1F24" if is_dark() else "#FFFFFF"
|
||||||
|
except Exception:
|
||||||
|
return "#FFFFFF"
|
||||||
|
|
||||||
|
|
||||||
|
def apply_result_chart_theme(self: "PQAutomationApp"):
|
||||||
|
"""统一刷新结果图画布背景,使其跟随浅/深色主题。"""
|
||||||
|
bg = _result_bg_color()
|
||||||
|
|
||||||
|
chart_pairs = [
|
||||||
|
("gamut_fig", "gamut_canvas"),
|
||||||
|
("gamma_fig", "gamma_canvas"),
|
||||||
|
("eotf_fig", "eotf_canvas"),
|
||||||
|
("cct_fig", "cct_canvas"),
|
||||||
|
("contrast_fig", "contrast_canvas"),
|
||||||
|
("accuracy_fig", "accuracy_canvas"),
|
||||||
|
]
|
||||||
|
|
||||||
|
for fig_attr, canvas_attr in chart_pairs:
|
||||||
|
fig = getattr(self, fig_attr, None)
|
||||||
|
canvas = getattr(self, canvas_attr, None)
|
||||||
|
if fig is not None:
|
||||||
|
fig.patch.set_facecolor(bg)
|
||||||
|
if canvas is not None:
|
||||||
|
try:
|
||||||
|
widget = canvas.get_tk_widget()
|
||||||
|
widget.configure(bg=bg, highlightthickness=0)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
canvas.draw_idle()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
@@ -988,6 +1027,7 @@ def create_result_chart_frame(self: "PQAutomationApp"):
|
|||||||
self.init_cct_chart()
|
self.init_cct_chart()
|
||||||
self.init_contrast_chart()
|
self.init_contrast_chart()
|
||||||
self.init_accuracy_chart()
|
self.init_accuracy_chart()
|
||||||
|
self.apply_result_chart_theme()
|
||||||
|
|
||||||
# 绑定Tab切换事件
|
# 绑定Tab切换事件
|
||||||
self.chart_notebook.bind("<<NotebookTabChanged>>", self.on_chart_tab_changed)
|
self.chart_notebook.bind("<<NotebookTabChanged>>", self.on_chart_tab_changed)
|
||||||
@@ -1026,6 +1066,7 @@ class ChartFrameMixin:
|
|||||||
init_cct_chart = init_cct_chart
|
init_cct_chart = init_cct_chart
|
||||||
init_contrast_chart = init_contrast_chart
|
init_contrast_chart = init_contrast_chart
|
||||||
init_accuracy_chart = init_accuracy_chart
|
init_accuracy_chart = init_accuracy_chart
|
||||||
|
apply_result_chart_theme = apply_result_chart_theme
|
||||||
_init_accuracy_result_table = _init_accuracy_result_table
|
_init_accuracy_result_table = _init_accuracy_result_table
|
||||||
clear_accuracy_result_table = clear_accuracy_result_table
|
clear_accuracy_result_table = clear_accuracy_result_table
|
||||||
update_accuracy_result_table = update_accuracy_result_table
|
update_accuracy_result_table = update_accuracy_result_table
|
||||||
|
|||||||
@@ -20,6 +20,21 @@ if TYPE_CHECKING:
|
|||||||
from pqAutomationApp import PQAutomationApp
|
from pqAutomationApp import PQAutomationApp
|
||||||
|
|
||||||
|
|
||||||
|
def _theme_colors():
|
||||||
|
style = ttk.Style()
|
||||||
|
colors = style.colors
|
||||||
|
return {
|
||||||
|
"bg": colors.bg,
|
||||||
|
"fg": colors.fg,
|
||||||
|
"muted": colors.secondary,
|
||||||
|
"input_bg": colors.inputbg,
|
||||||
|
"input_fg": colors.inputfg,
|
||||||
|
"select_bg": colors.selectbg,
|
||||||
|
"select_fg": colors.selectfg,
|
||||||
|
"border": colors.border,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -50,6 +65,7 @@ def create_ai_image_panel(self: "PQAutomationApp"):
|
|||||||
container.columnconfigure(0, weight=0)
|
container.columnconfigure(0, weight=0)
|
||||||
container.columnconfigure(1, weight=1)
|
container.columnconfigure(1, weight=1)
|
||||||
container.rowconfigure(0, weight=1)
|
container.rowconfigure(0, weight=1)
|
||||||
|
palette = _theme_colors()
|
||||||
|
|
||||||
left = ttk.Frame(container, width=360)
|
left = ttk.Frame(container, width=360)
|
||||||
left.grid(row=0, column=0, sticky=tk.NS, padx=(0, 10))
|
left.grid(row=0, column=0, sticky=tk.NS, padx=(0, 10))
|
||||||
@@ -72,10 +88,12 @@ def create_ai_image_panel(self: "PQAutomationApp"):
|
|||||||
bd=1,
|
bd=1,
|
||||||
relief=tk.FLAT,
|
relief=tk.FLAT,
|
||||||
highlightthickness=1,
|
highlightthickness=1,
|
||||||
highlightbackground="#d8d8d8",
|
bg=palette["input_bg"],
|
||||||
highlightcolor="#4a90e2",
|
fg=palette["input_fg"],
|
||||||
selectbackground="#2b6cb0",
|
highlightbackground=palette["border"],
|
||||||
selectforeground="#ffffff",
|
highlightcolor=palette["select_bg"],
|
||||||
|
selectbackground=palette["select_bg"],
|
||||||
|
selectforeground=palette["select_fg"],
|
||||||
yscrollcommand=scroll.set,
|
yscrollcommand=scroll.set,
|
||||||
)
|
)
|
||||||
scroll.config(command=self.ai_image_listbox.yview)
|
scroll.config(command=self.ai_image_listbox.yview)
|
||||||
@@ -135,7 +153,7 @@ def create_ai_image_panel(self: "PQAutomationApp"):
|
|||||||
preview_frame.pack(fill=tk.BOTH, expand=True)
|
preview_frame.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
self.ai_image_canvas = tk.Canvas(
|
self.ai_image_canvas = tk.Canvas(
|
||||||
preview_frame, bg="#1e1e1e", highlightthickness=0
|
preview_frame, bg=palette["bg"], highlightthickness=0
|
||||||
)
|
)
|
||||||
self.ai_image_canvas.pack(fill=tk.BOTH, expand=True)
|
self.ai_image_canvas.pack(fill=tk.BOTH, expand=True)
|
||||||
self.ai_image_canvas.bind("<Configure>", lambda e: _redraw_preview(self))
|
self.ai_image_canvas.bind("<Configure>", lambda e: _redraw_preview(self))
|
||||||
@@ -145,14 +163,21 @@ def create_ai_image_panel(self: "PQAutomationApp"):
|
|||||||
self.ai_image_meta_var = tk.StringVar(value="未选择图片")
|
self.ai_image_meta_var = tk.StringVar(value="未选择图片")
|
||||||
ttk.Label(
|
ttk.Label(
|
||||||
meta_row, textvariable=self.ai_image_meta_var,
|
meta_row, textvariable=self.ai_image_meta_var,
|
||||||
foreground="#666", font=("微软雅黑", 9),
|
foreground=palette["muted"], font=("微软雅黑", 9),
|
||||||
).pack(side=tk.LEFT)
|
).pack(side=tk.LEFT)
|
||||||
|
|
||||||
# 输入区
|
# 输入区
|
||||||
input_frame = ttk.LabelFrame(right, text="提示输入(Ctrl+Enter 发送)", padding=6)
|
input_frame = ttk.LabelFrame(right, text="提示输入(Ctrl+Enter 发送)", padding=6)
|
||||||
input_frame.pack(fill=tk.X, pady=(4, 0))
|
input_frame.pack(fill=tk.X, pady=(4, 0))
|
||||||
|
|
||||||
self.ai_image_input = tk.Text(input_frame, height=3, wrap=tk.WORD)
|
self.ai_image_input = tk.Text(
|
||||||
|
input_frame,
|
||||||
|
height=3,
|
||||||
|
wrap=tk.WORD,
|
||||||
|
bg=palette["input_bg"],
|
||||||
|
fg=palette["input_fg"],
|
||||||
|
insertbackground=palette["input_fg"],
|
||||||
|
)
|
||||||
self.ai_image_input.pack(fill=tk.X, side=tk.TOP)
|
self.ai_image_input.pack(fill=tk.X, side=tk.TOP)
|
||||||
self.ai_image_input.bind("<Control-Return>", lambda e: (_send_prompt(self), "break"))
|
self.ai_image_input.bind("<Control-Return>", lambda e: (_send_prompt(self), "break"))
|
||||||
|
|
||||||
@@ -161,7 +186,7 @@ def create_ai_image_panel(self: "PQAutomationApp"):
|
|||||||
self.ai_image_status_var = tk.StringVar(value="就绪")
|
self.ai_image_status_var = tk.StringVar(value="就绪")
|
||||||
ttk.Label(
|
ttk.Label(
|
||||||
send_row, textvariable=self.ai_image_status_var,
|
send_row, textvariable=self.ai_image_status_var,
|
||||||
foreground="#888", font=("微软雅黑", 9),
|
foreground=palette["muted"], font=("微软雅黑", 9),
|
||||||
).pack(side=tk.LEFT)
|
).pack(side=tk.LEFT)
|
||||||
self.ai_image_progress = ttk.Progressbar(
|
self.ai_image_progress = ttk.Progressbar(
|
||||||
send_row,
|
send_row,
|
||||||
@@ -220,6 +245,7 @@ def reload_ai_image_list(self: "PQAutomationApp", auto_select_first=True):
|
|||||||
其下列出该轮生成的所有图片。会话按"最近使用"倒序,组内按时间倒序。
|
其下列出该轮生成的所有图片。会话按"最近使用"倒序,组内按时间倒序。
|
||||||
auto_select_first: 是否自动选中第一张图片(默认 True)。
|
auto_select_first: 是否自动选中第一张图片(默认 True)。
|
||||||
"""
|
"""
|
||||||
|
palette = _theme_colors()
|
||||||
self.ai_image_records = _svc.list_records(base_dir=_get_app_base_dir(self))
|
self.ai_image_records = _svc.list_records(base_dir=_get_app_base_dir(self))
|
||||||
self.ai_image_listbox.delete(0, tk.END)
|
self.ai_image_listbox.delete(0, tk.END)
|
||||||
# 维护行号 → 记录索引的映射;分隔头处为 None
|
# 维护行号 → 记录索引的映射;分隔头处为 None
|
||||||
@@ -236,8 +262,8 @@ def reload_ai_image_list(self: "PQAutomationApp", auto_select_first=True):
|
|||||||
# 头部行:禁用选中(视觉上变灰)
|
# 头部行:禁用选中(视觉上变灰)
|
||||||
last = self.ai_image_listbox.size() - 1
|
last = self.ai_image_listbox.size() - 1
|
||||||
self.ai_image_listbox.itemconfig(
|
self.ai_image_listbox.itemconfig(
|
||||||
last, foreground="#888", selectforeground="#888",
|
last, foreground=palette["muted"], selectforeground=palette["muted"],
|
||||||
background="#f5f5f5", selectbackground="#f5f5f5",
|
background=palette["bg"], selectbackground=palette["bg"],
|
||||||
)
|
)
|
||||||
self._ai_image_row_map.append(None)
|
self._ai_image_row_map.append(None)
|
||||||
self._ai_image_row_session_map.append(sid)
|
self._ai_image_row_session_map.append(sid)
|
||||||
@@ -331,6 +357,7 @@ def _select_record(self: "PQAutomationApp", rec: _svc.AIImageRecord):
|
|||||||
def _redraw_preview(self: "PQAutomationApp"):
|
def _redraw_preview(self: "PQAutomationApp"):
|
||||||
rec = getattr(self, "ai_image_current", None)
|
rec = getattr(self, "ai_image_current", None)
|
||||||
canvas = self.ai_image_canvas
|
canvas = self.ai_image_canvas
|
||||||
|
palette = _theme_colors()
|
||||||
canvas.delete("all")
|
canvas.delete("all")
|
||||||
if rec is None or not os.path.isfile(rec.image_path):
|
if rec is None or not os.path.isfile(rec.image_path):
|
||||||
return
|
return
|
||||||
@@ -340,7 +367,7 @@ def _redraw_preview(self: "PQAutomationApp"):
|
|||||||
img = Image.open(rec.image_path)
|
img = Image.open(rec.image_path)
|
||||||
img.load()
|
img.load()
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
canvas.create_text(cw // 2, ch // 2, text=f"加载失败: {exc}", fill="#f66")
|
canvas.create_text(cw // 2, ch // 2, text=f"加载失败: {exc}", fill=palette["select_bg"])
|
||||||
return
|
return
|
||||||
iw, ih = img.size
|
iw, ih = img.size
|
||||||
scale = min(cw / iw, ch / ih, 1.0)
|
scale = min(cw / iw, ch / ih, 1.0)
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ if TYPE_CHECKING:
|
|||||||
from pqAutomationApp import PQAutomationApp
|
from pqAutomationApp import PQAutomationApp
|
||||||
|
|
||||||
|
|
||||||
|
def _theme_colors():
|
||||||
|
style = ttk.Style()
|
||||||
|
colors = style.colors
|
||||||
|
return {
|
||||||
|
"muted": colors.secondary,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_cct_params_frame(self: "PQAutomationApp"):
|
def create_cct_params_frame(self: "PQAutomationApp"):
|
||||||
"""创建色度参数设置区域 - 屏模组、SDR、HDR 独立(增加色域参考标准选择 + 单步调试按钮)"""
|
"""创建色度参数设置区域 - 屏模组、SDR、HDR 独立(增加色域参考标准选择 + 单步调试按钮)"""
|
||||||
@@ -122,7 +130,7 @@ def create_cct_params_frame(self: "PQAutomationApp"):
|
|||||||
self.cct_params_frame,
|
self.cct_params_frame,
|
||||||
text="提示: 清空输入框将恢复默认值",
|
text="提示: 清空输入框将恢复默认值",
|
||||||
font=("SimHei", 8),
|
font=("SimHei", 8),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
||||||
|
|
||||||
# ==================== SDR 色度参数 Frame ====================
|
# ==================== SDR 色度参数 Frame ====================
|
||||||
@@ -227,7 +235,7 @@ def create_cct_params_frame(self: "PQAutomationApp"):
|
|||||||
self.sdr_cct_params_frame,
|
self.sdr_cct_params_frame,
|
||||||
text="提示: 清空输入框将恢复默认值",
|
text="提示: 清空输入框将恢复默认值",
|
||||||
font=("SimHei", 8),
|
font=("SimHei", 8),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
||||||
|
|
||||||
# ==================== HDR 色度参数 Frame ====================
|
# ==================== HDR 色度参数 Frame ====================
|
||||||
@@ -332,7 +340,7 @@ def create_cct_params_frame(self: "PQAutomationApp"):
|
|||||||
self.hdr_cct_params_frame,
|
self.hdr_cct_params_frame,
|
||||||
text="提示: 清空输入框将恢复默认值",
|
text="提示: 清空输入框将恢复默认值",
|
||||||
font=("SimHei", 8),
|
font=("SimHei", 8),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
).grid(row=5, column=0, columnspan=4, sticky=tk.W, padx=5, pady=5)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -718,6 +718,11 @@ def _on_toggle_theme(self: "PQAutomationApp") -> None:
|
|||||||
from app.views.theme_manager import toggle_theme
|
from app.views.theme_manager import toggle_theme
|
||||||
toggle_theme()
|
toggle_theme()
|
||||||
_refresh_theme_toggle_label(self)
|
_refresh_theme_toggle_label(self)
|
||||||
|
if hasattr(self, "apply_result_chart_theme"):
|
||||||
|
try:
|
||||||
|
self.apply_result_chart_theme()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
# 同步刷新侧栏选中态(高亮样式跟随新色板)
|
# 同步刷新侧栏选中态(高亮样式跟随新色板)
|
||||||
if hasattr(self, "update_sidebar_selection"):
|
if hasattr(self, "update_sidebar_selection"):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -10,6 +10,18 @@ import threading
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def _theme_colors():
|
||||||
|
style = ttk.Style()
|
||||||
|
colors = style.colors
|
||||||
|
return {
|
||||||
|
"fg": colors.fg,
|
||||||
|
"muted": colors.secondary,
|
||||||
|
"info": colors.info,
|
||||||
|
"warning": colors.warning,
|
||||||
|
"error": colors.danger,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class PQDebugPanel:
|
class PQDebugPanel:
|
||||||
"""PQ 单步调试面板 - 支持 Gamma/EOTF/色准单步测试"""
|
"""PQ 单步调试面板 - 支持 Gamma/EOTF/色准单步测试"""
|
||||||
|
|
||||||
@@ -72,7 +84,7 @@ class PQDebugPanel:
|
|||||||
self.screen_gamma_frame,
|
self.screen_gamma_frame,
|
||||||
text="测试完成后可用,选择灰阶进行单步调试",
|
text="测试完成后可用,选择灰阶进行单步调试",
|
||||||
font=("SimHei", 9),
|
font=("SimHei", 9),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
||||||
|
|
||||||
# 灰阶选择
|
# 灰阶选择
|
||||||
@@ -137,7 +149,7 @@ class PQDebugPanel:
|
|||||||
self.screen_rgb_frame,
|
self.screen_rgb_frame,
|
||||||
text="测试完成后可用,选择颜色进行单步调试",
|
text="测试完成后可用,选择颜色进行单步调试",
|
||||||
font=("SimHei", 9),
|
font=("SimHei", 9),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
||||||
|
|
||||||
# RGB 颜色选择
|
# RGB 颜色选择
|
||||||
@@ -210,7 +222,7 @@ class PQDebugPanel:
|
|||||||
self.sdr_gamma_frame,
|
self.sdr_gamma_frame,
|
||||||
text="测试完成后可用,选择灰阶进行单步调试",
|
text="测试完成后可用,选择灰阶进行单步调试",
|
||||||
font=("SimHei", 9),
|
font=("SimHei", 9),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
||||||
|
|
||||||
ttk.Label(self.sdr_gamma_frame, text="选择灰阶:").grid(
|
ttk.Label(self.sdr_gamma_frame, text="选择灰阶:").grid(
|
||||||
@@ -272,7 +284,7 @@ class PQDebugPanel:
|
|||||||
self.sdr_accuracy_frame,
|
self.sdr_accuracy_frame,
|
||||||
text="测试完成后可用,选择色块进行单步调试",
|
text="测试完成后可用,选择色块进行单步调试",
|
||||||
font=("SimHei", 9),
|
font=("SimHei", 9),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
||||||
|
|
||||||
ttk.Label(self.sdr_accuracy_frame, text="选择色块:").grid(
|
ttk.Label(self.sdr_accuracy_frame, text="选择色块:").grid(
|
||||||
@@ -334,7 +346,7 @@ class PQDebugPanel:
|
|||||||
self.sdr_rgb_frame,
|
self.sdr_rgb_frame,
|
||||||
text="测试完成后可用,选择颜色进行单步调试",
|
text="测试完成后可用,选择颜色进行单步调试",
|
||||||
font=("SimHei", 9),
|
font=("SimHei", 9),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
||||||
|
|
||||||
# RGB 颜色选择
|
# RGB 颜色选择
|
||||||
@@ -407,7 +419,7 @@ class PQDebugPanel:
|
|||||||
self.hdr_eotf_frame,
|
self.hdr_eotf_frame,
|
||||||
text="测试完成后可用,选择灰阶进行单步调试",
|
text="测试完成后可用,选择灰阶进行单步调试",
|
||||||
font=("SimHei", 9),
|
font=("SimHei", 9),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
||||||
|
|
||||||
ttk.Label(self.hdr_eotf_frame, text="选择灰阶:").grid(
|
ttk.Label(self.hdr_eotf_frame, text="选择灰阶:").grid(
|
||||||
@@ -469,7 +481,7 @@ class PQDebugPanel:
|
|||||||
self.hdr_accuracy_frame,
|
self.hdr_accuracy_frame,
|
||||||
text="测试完成后可用,选择色块进行单步调试",
|
text="测试完成后可用,选择色块进行单步调试",
|
||||||
font=("SimHei", 9),
|
font=("SimHei", 9),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
||||||
|
|
||||||
ttk.Label(self.hdr_accuracy_frame, text="选择色块:").grid(
|
ttk.Label(self.hdr_accuracy_frame, text="选择色块:").grid(
|
||||||
@@ -531,7 +543,7 @@ class PQDebugPanel:
|
|||||||
self.hdr_rgb_frame,
|
self.hdr_rgb_frame,
|
||||||
text="测试完成后可用,选择颜色进行单步调试",
|
text="测试完成后可用,选择颜色进行单步调试",
|
||||||
font=("SimHei", 9),
|
font=("SimHei", 9),
|
||||||
foreground="gray",
|
foreground=_theme_colors()["muted"],
|
||||||
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
).grid(row=0, column=0, columnspan=3, pady=(0, 10))
|
||||||
|
|
||||||
# RGB 颜色选择
|
# RGB 颜色选择
|
||||||
@@ -1007,12 +1019,13 @@ class PQDebugPanel:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 设置标签样式
|
# 设置标签样式
|
||||||
tree.tag_configure("header", background="#E3F2FD", font=("SimHei", 9, "bold"))
|
palette = _theme_colors()
|
||||||
tree.tag_configure("normal", foreground="black")
|
tree.tag_configure("header", background=palette["info"], font=("SimHei", 9, "bold"))
|
||||||
tree.tag_configure("warning", foreground="red")
|
tree.tag_configure("normal", foreground=palette["fg"])
|
||||||
tree.tag_configure("highlight", foreground="blue", font=("SimHei", 9, "bold"))
|
tree.tag_configure("warning", foreground=palette["warning"])
|
||||||
|
tree.tag_configure("highlight", foreground=palette["info"], font=("SimHei", 9, "bold"))
|
||||||
tree.tag_configure(
|
tree.tag_configure(
|
||||||
"highlight_warning", foreground="red", font=("SimHei", 9, "bold")
|
"highlight_warning", foreground=palette["warning"], font=("SimHei", 9, "bold")
|
||||||
)
|
)
|
||||||
|
|
||||||
def _disable_test_button(self, test_type, test_item):
|
def _disable_test_button(self, test_type, test_item):
|
||||||
|
|||||||
@@ -17,6 +17,22 @@ _GUI_LEVEL_TO_LOG = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _theme_colors():
|
||||||
|
style = ttk.Style()
|
||||||
|
colors = style.colors
|
||||||
|
return {
|
||||||
|
"bg": colors.bg,
|
||||||
|
"fg": colors.fg,
|
||||||
|
"muted": colors.secondary,
|
||||||
|
"accent": colors.info,
|
||||||
|
"warning": colors.warning,
|
||||||
|
"error": colors.danger,
|
||||||
|
"success": colors.success,
|
||||||
|
"text_bg": colors.inputbg,
|
||||||
|
"text_fg": colors.inputfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class PQLogGUI(ttk.Frame):
|
class PQLogGUI(ttk.Frame):
|
||||||
VALID_LEVELS = {"info", "success", "warning", "error", "debug", "separator", "blank"}
|
VALID_LEVELS = {"info", "success", "warning", "error", "debug", "separator", "blank"}
|
||||||
|
|
||||||
@@ -53,21 +69,22 @@ class PQLogGUI(ttk.Frame):
|
|||||||
text_container = ttk.Frame(log_frame)
|
text_container = ttk.Frame(log_frame)
|
||||||
text_container.pack(fill=tk.BOTH, expand=True, padx=6, pady=(0, 6))
|
text_container.pack(fill=tk.BOTH, expand=True, padx=6, pady=(0, 6))
|
||||||
|
|
||||||
|
palette = _theme_colors()
|
||||||
self.log_text = tk.Text(
|
self.log_text = tk.Text(
|
||||||
text_container,
|
text_container,
|
||||||
height=10,
|
height=10,
|
||||||
width=50,
|
width=50,
|
||||||
wrap=tk.WORD,
|
wrap=tk.WORD,
|
||||||
font=("Consolas", 10),
|
font=("Consolas", 10),
|
||||||
bg="#fbfcfe",
|
bg=palette["text_bg"],
|
||||||
fg="#1f2937",
|
fg=palette["text_fg"],
|
||||||
relief=tk.FLAT,
|
relief=tk.FLAT,
|
||||||
bd=0,
|
bd=0,
|
||||||
padx=10,
|
padx=10,
|
||||||
pady=8,
|
pady=8,
|
||||||
spacing1=2,
|
spacing1=2,
|
||||||
spacing3=2,
|
spacing3=2,
|
||||||
insertbackground="#1f2937",
|
insertbackground=palette["text_fg"],
|
||||||
)
|
)
|
||||||
self.log_text.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
|
self.log_text.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
|
||||||
|
|
||||||
@@ -114,19 +131,20 @@ class PQLogGUI(ttk.Frame):
|
|||||||
self._update_summary()
|
self._update_summary()
|
||||||
|
|
||||||
def _configure_tags(self):
|
def _configure_tags(self):
|
||||||
self.log_text.tag_configure("timestamp", foreground="#6b7280")
|
palette = _theme_colors()
|
||||||
self.log_text.tag_configure("level_info", foreground="#2563eb")
|
self.log_text.tag_configure("timestamp", foreground=palette["muted"])
|
||||||
self.log_text.tag_configure("level_success", foreground="#0f766e")
|
self.log_text.tag_configure("level_info", foreground=palette["accent"])
|
||||||
self.log_text.tag_configure("level_warning", foreground="#b45309")
|
self.log_text.tag_configure("level_success", foreground=palette["success"])
|
||||||
self.log_text.tag_configure("level_error", foreground="#b91c1c")
|
self.log_text.tag_configure("level_warning", foreground=palette["warning"])
|
||||||
|
self.log_text.tag_configure("level_error", foreground=palette["error"])
|
||||||
self.log_text.tag_configure("level_debug", foreground="#7c3aed")
|
self.log_text.tag_configure("level_debug", foreground="#7c3aed")
|
||||||
self.log_text.tag_configure("message", foreground="#1f2937")
|
self.log_text.tag_configure("message", foreground=palette["fg"])
|
||||||
self.log_text.tag_configure("message_success", foreground="#0f766e")
|
self.log_text.tag_configure("message_success", foreground=palette["success"])
|
||||||
self.log_text.tag_configure("message_warning", foreground="#b45309")
|
self.log_text.tag_configure("message_warning", foreground=palette["warning"])
|
||||||
self.log_text.tag_configure("message_error", foreground="#991b1b")
|
self.log_text.tag_configure("message_error", foreground=palette["error"])
|
||||||
self.log_text.tag_configure("message_debug", foreground="#6d28d9")
|
self.log_text.tag_configure("message_debug", foreground="#6d28d9")
|
||||||
self.log_text.tag_configure("separator", foreground="#94a3b8")
|
self.log_text.tag_configure("separator", foreground=palette["muted"])
|
||||||
self.log_text.tag_configure("traceback", foreground="#7f1d1d")
|
self.log_text.tag_configure("traceback", foreground=palette["error"])
|
||||||
self.log_text.tag_configure("blank", spacing1=4, spacing3=4)
|
self.log_text.tag_configure("blank", spacing1=4, spacing3=4)
|
||||||
|
|
||||||
def _append_message(self, message, level):
|
def _append_message(self, message, level):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"current_test_type": "screen_module",
|
"current_test_type": "hdr_movie",
|
||||||
"test_types": {
|
"test_types": {
|
||||||
"screen_module": {
|
"screen_module": {
|
||||||
"name": "屏模组性能测试",
|
"name": "屏模组性能测试",
|
||||||
|
|||||||
Reference in New Issue
Block a user