修改UCD逻辑、添加关闭界面的x
This commit is contained in:
@@ -78,12 +78,21 @@ class ConnectionController:
|
|||||||
|
|
||||||
# -- UCD 连接 ------------------------------------------------
|
# -- UCD 连接 ------------------------------------------------
|
||||||
|
|
||||||
|
def _pick_ucd_device(self, ucd_list: list[str], display: str) -> str | None:
|
||||||
|
"""Prefer devices not marked in-use; fall back to full list."""
|
||||||
|
usable = [d for d in ucd_list if "(in use)" not in d.lower()]
|
||||||
|
if display in usable:
|
||||||
|
return display
|
||||||
|
if usable:
|
||||||
|
return usable[0]
|
||||||
|
if display in ucd_list:
|
||||||
|
return display
|
||||||
|
return ucd_list[0] if ucd_list else None
|
||||||
|
|
||||||
def _refresh_ucd_selection(self, display: str) -> tuple[list[str], str | None]:
|
def _refresh_ucd_selection(self, display: str) -> tuple[list[str], str | None]:
|
||||||
"""Rescan devices and return (device list, valid selection or None)."""
|
"""Rescan devices and return (device list, valid selection or None)."""
|
||||||
ucd_list = self.list_ucd_devices()
|
ucd_list = self.list_ucd_devices()
|
||||||
if display in ucd_list:
|
return ucd_list, self._pick_ucd_device(ucd_list, display)
|
||||||
return ucd_list, display
|
|
||||||
return ucd_list, (ucd_list[0] if ucd_list else None)
|
|
||||||
|
|
||||||
def _sync_ucd_combo(self, ucd_list: list[str], selected: str) -> None:
|
def _sync_ucd_combo(self, ucd_list: list[str], selected: str) -> None:
|
||||||
app = self._app
|
app = self._app
|
||||||
@@ -91,6 +100,19 @@ class ConnectionController:
|
|||||||
app.ucd_list_var.set(selected)
|
app.ucd_list_var.set(selected)
|
||||||
app.update_config()
|
app.update_config()
|
||||||
|
|
||||||
|
def _prepare_ucd_reconnect(self) -> None:
|
||||||
|
"""Release stale SDK/native handles before a new open attempt."""
|
||||||
|
if self._device.state.name != "CLOSED":
|
||||||
|
try:
|
||||||
|
self._device.close()
|
||||||
|
return
|
||||||
|
except Exception as exc: # noqa: BLE001
|
||||||
|
self._log(f"关闭旧 UCD 会话失败,将强制重置: {exc}", level="info")
|
||||||
|
try:
|
||||||
|
self._device.force_reset()
|
||||||
|
except Exception as exc: # noqa: BLE001
|
||||||
|
self._log(f"强制重置 UCD SDK 失败: {exc}", level="error")
|
||||||
|
|
||||||
def connect_ucd(self, display: str, *, rescan: bool = True) -> bool:
|
def connect_ucd(self, display: str, *, rescan: bool = True) -> bool:
|
||||||
"""打开指定 UCD 设备。成功返回 True。"""
|
"""打开指定 UCD 设备。成功返回 True。"""
|
||||||
if rescan:
|
if rescan:
|
||||||
@@ -99,26 +121,48 @@ class ConnectionController:
|
|||||||
self._log("未检测到 UCD 设备,请确认电源已打开后重试", level="error")
|
self._log("未检测到 UCD 设备,请确认电源已打开后重试", level="error")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self._device.state.name != "CLOSED":
|
self._prepare_ucd_reconnect()
|
||||||
|
|
||||||
|
last_error: Exception | None = None
|
||||||
|
for attempt in range(2):
|
||||||
try:
|
try:
|
||||||
self._device.close()
|
self._device.open(DeviceInfo.parse(display))
|
||||||
except Exception: # noqa: BLE001
|
return True
|
||||||
pass
|
except UcdError as exc:
|
||||||
try:
|
last_error = exc
|
||||||
self._device.open(DeviceInfo.parse(display))
|
self._log(
|
||||||
return True
|
f"设备 {display} 连接失败 ({attempt + 1}/2): {exc}",
|
||||||
except UcdError as exc:
|
level="error",
|
||||||
self._log(f"设备 {display} 异常,UCD323 连接失败: {exc}", level="error")
|
)
|
||||||
return False
|
except Exception as exc: # noqa: BLE001
|
||||||
except Exception as exc: # noqa: BLE001
|
last_error = exc
|
||||||
self._log(f"UCD323 连接异常: {exc}", level="error")
|
self._log(
|
||||||
return False
|
f"UCD323 连接异常 ({attempt + 1}/2): {exc}",
|
||||||
|
level="error",
|
||||||
|
)
|
||||||
|
|
||||||
|
if attempt == 0:
|
||||||
|
try:
|
||||||
|
self._device.force_reset()
|
||||||
|
except Exception as exc: # noqa: BLE001
|
||||||
|
self._log(f"重连前强制重置 UCD 失败: {exc}", level="error")
|
||||||
|
if rescan:
|
||||||
|
_, display = self._refresh_ucd_selection(display)
|
||||||
|
if not display:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if last_error is not None:
|
||||||
|
self._log(f"UCD323 重连失败: {last_error}", level="error")
|
||||||
|
return False
|
||||||
|
|
||||||
def disconnect_ucd(self) -> None:
|
def disconnect_ucd(self) -> None:
|
||||||
try:
|
try:
|
||||||
self._device.close()
|
self._device.close()
|
||||||
except Exception: # noqa: BLE001
|
except Exception: # noqa: BLE001
|
||||||
pass
|
try:
|
||||||
|
self._device.force_reset()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
pass
|
||||||
self._log("UCD连接已断开", level="info")
|
self._log("UCD连接已断开", level="info")
|
||||||
|
|
||||||
# -- CA 连接 -------------------------------------------------
|
# -- CA 连接 -------------------------------------------------
|
||||||
@@ -297,9 +341,15 @@ class ConnectionController:
|
|||||||
app = self._app
|
app = self._app
|
||||||
com_ports = self.list_com_ports()
|
com_ports = self.list_com_ports()
|
||||||
ucd_list = self.list_ucd_devices()
|
ucd_list = self.list_ucd_devices()
|
||||||
|
if not ucd_list or all("(in use)" in d.lower() for d in ucd_list):
|
||||||
|
try:
|
||||||
|
self._device.force_reset()
|
||||||
|
except Exception as exc: # noqa: BLE001
|
||||||
|
self._log(f"刷新时重置 UCD SDK: {exc}", level="info")
|
||||||
|
ucd_list = self.list_ucd_devices()
|
||||||
|
|
||||||
if app.ucd_list_var.get() not in ucd_list:
|
selected = self._pick_ucd_device(ucd_list, app.ucd_list_var.get())
|
||||||
app.ucd_list_var.set(ucd_list[0] if ucd_list else "")
|
app.ucd_list_var.set(selected or "")
|
||||||
app.ucd_list_combo.config(values=ucd_list)
|
app.ucd_list_combo.config(values=ucd_list)
|
||||||
|
|
||||||
if app.ca_com_var.get() not in com_ports:
|
if app.ca_com_var.get() not in com_ports:
|
||||||
|
|||||||
@@ -156,8 +156,7 @@ class _UcdSdkBackend:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._force_cleanup()
|
self.hard_reset()
|
||||||
self._reinit_tsi_lib()
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
@@ -168,19 +167,24 @@ class _UcdSdkBackend:
|
|||||||
self._stop_audio_output()
|
self._stop_audio_output()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
self._close_device_object(self.dev)
|
try:
|
||||||
|
self._close_device_object(self.dev)
|
||||||
self._reset_state()
|
except Exception:
|
||||||
self._reinit_tsi_lib()
|
log.exception("UcdSdk.close device object failed")
|
||||||
return True
|
finally:
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
self._reset_state()
|
self._reset_state()
|
||||||
try:
|
try:
|
||||||
self._reinit_tsi_lib()
|
self._reinit_tsi_lib()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
log.exception("UcdSdk.close reinit failed")
|
||||||
return False
|
return True
|
||||||
|
|
||||||
|
def hard_reset(self) -> None:
|
||||||
|
"""丢弃失效句柄并重建 TSI(意外断连后重连前调用)。"""
|
||||||
|
self.dev = None
|
||||||
|
self.role = None
|
||||||
|
self._reset_state()
|
||||||
|
self._reinit_tsi_lib()
|
||||||
|
|
||||||
def _ensure_tsi_lib(self) -> None:
|
def _ensure_tsi_lib(self) -> None:
|
||||||
if self.lUniTAP is None:
|
if self.lUniTAP is None:
|
||||||
@@ -188,7 +192,13 @@ class _UcdSdkBackend:
|
|||||||
|
|
||||||
def _reinit_tsi_lib(self) -> None:
|
def _reinit_tsi_lib(self) -> None:
|
||||||
"""Destroy and recreate TsiLib so the native driver rescans USB devices."""
|
"""Destroy and recreate TsiLib so the native driver rescans USB devices."""
|
||||||
|
old = self.lUniTAP
|
||||||
self.lUniTAP = None
|
self.lUniTAP = None
|
||||||
|
if old is not None:
|
||||||
|
try:
|
||||||
|
old.cleanup()
|
||||||
|
except Exception:
|
||||||
|
log.exception("UcdSdk._reinit_tsi_lib cleanup failed")
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
gc.collect()
|
gc.collect()
|
||||||
time.sleep(2.0)
|
time.sleep(2.0)
|
||||||
@@ -1068,6 +1078,26 @@ class UCD323Device(IUcdDevice):
|
|||||||
self._info = None
|
self._info = None
|
||||||
self._bus.publish(ConnectionChanged(DeviceKind.UCD, False, prev_serial))
|
self._bus.publish(ConnectionChanged(DeviceKind.UCD, False, prev_serial))
|
||||||
|
|
||||||
|
def force_reset(self) -> None:
|
||||||
|
"""释放失效的 SDK 句柄,软件状态复位为 CLOSED(意外断连后重连前调用)。"""
|
||||||
|
with self._acquire_device_lock("force_reset"):
|
||||||
|
was_open = self._state != UcdState.CLOSED
|
||||||
|
prev_serial = self._info.serial if self._info else None
|
||||||
|
try:
|
||||||
|
self._sdk.hard_reset()
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
log.exception("UCD force_reset SDK failed")
|
||||||
|
self._state = UcdState.CLOSED
|
||||||
|
self._curr_signal = None
|
||||||
|
self._curr_timing = None
|
||||||
|
self._curr_pattern = None
|
||||||
|
self._last_applied = None
|
||||||
|
self._info = None
|
||||||
|
if was_open:
|
||||||
|
self._bus.publish(
|
||||||
|
ConnectionChanged(DeviceKind.UCD, False, prev_serial)
|
||||||
|
)
|
||||||
|
|
||||||
# --- 信号 / 图案配置 ---
|
# --- 信号 / 图案配置 ---
|
||||||
|
|
||||||
def configure(self, signal: SignalFormat, timing: TimingSpec) -> bool:
|
def configure(self, signal: SignalFormat, timing: TimingSpec) -> bool:
|
||||||
|
|||||||
@@ -3,19 +3,174 @@
|
|||||||
register_panel / show_panel / hide_all_panels —— 在右侧栏不同浮动面板间切换。
|
register_panel / show_panel / hide_all_panels —— 在右侧栏不同浮动面板间切换。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import tkinter as tk
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
import tkinter as tk
|
||||||
|
import tkinter.font as tkfont
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Any, Callable
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from pqAutomationApp import PQAutomationApp
|
from pqAutomationApp import PQAutomationApp
|
||||||
|
|
||||||
|
|
||||||
|
def create_tool_panel_sidebar_item(
|
||||||
|
self: "PQAutomationApp", parent: tk.Misc, label: str, command: Callable[[], None]
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
"""创建工具面板侧栏项:名称左对齐,选中时 × 贴右端,整体可点击。"""
|
||||||
|
from app.views.modern_styles import _contrast_text, _is_dark, get_theme_palette
|
||||||
|
|
||||||
|
row = tk.Frame(parent, bd=0, highlightthickness=0, cursor="hand2")
|
||||||
|
name_lbl = tk.Label(row, text=label, anchor=tk.W, bd=0, padx=18, pady=9)
|
||||||
|
close_lbl = tk.Label(
|
||||||
|
row,
|
||||||
|
text="×",
|
||||||
|
anchor=tk.CENTER,
|
||||||
|
bd=0,
|
||||||
|
padx=0,
|
||||||
|
pady=9,
|
||||||
|
width=2,
|
||||||
|
font=("Segoe UI", 9),
|
||||||
|
)
|
||||||
|
name_lbl.pack(side=tk.LEFT, fill=tk.X, expand=True)
|
||||||
|
|
||||||
|
item: dict[str, Any] = {
|
||||||
|
"row": row,
|
||||||
|
"name_label": name_lbl,
|
||||||
|
"close_label": close_lbl,
|
||||||
|
"label": label,
|
||||||
|
"selected": False,
|
||||||
|
"hover": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _apply_style() -> None:
|
||||||
|
palette = get_theme_palette()
|
||||||
|
sidebar_bg = palette["sidebar_bg"]
|
||||||
|
sidebar_hover = palette["sidebar_hover"]
|
||||||
|
sidebar_selected = palette["sidebar_selected"]
|
||||||
|
sidebar_fg = palette["sidebar_fg"]
|
||||||
|
selected_fg = _contrast_text(
|
||||||
|
sidebar_selected,
|
||||||
|
dark_text=palette["badge_fg"],
|
||||||
|
light_text=sidebar_fg,
|
||||||
|
)
|
||||||
|
|
||||||
|
if item["selected"]:
|
||||||
|
bg = sidebar_selected
|
||||||
|
fg = selected_fg
|
||||||
|
name_font = ("Segoe UI Semibold", 10)
|
||||||
|
elif item["hover"]:
|
||||||
|
bg = sidebar_hover
|
||||||
|
fg = "#ffffff" if _is_dark(sidebar_hover) else sidebar_fg
|
||||||
|
name_font = ("Segoe UI", 10)
|
||||||
|
else:
|
||||||
|
bg = sidebar_bg
|
||||||
|
fg = sidebar_fg
|
||||||
|
name_font = ("Segoe UI", 10)
|
||||||
|
|
||||||
|
row.configure(bg=bg)
|
||||||
|
for widget in (name_lbl, close_lbl):
|
||||||
|
widget.configure(
|
||||||
|
bg=bg,
|
||||||
|
fg=fg,
|
||||||
|
activebackground=bg,
|
||||||
|
activeforeground=fg,
|
||||||
|
)
|
||||||
|
name_lbl.configure(font=name_font)
|
||||||
|
|
||||||
|
def _truncate_name() -> None:
|
||||||
|
full = item["label"]
|
||||||
|
if not item["selected"]:
|
||||||
|
name_lbl.configure(text=full)
|
||||||
|
return
|
||||||
|
|
||||||
|
row.update_idletasks()
|
||||||
|
close_w = close_lbl.winfo_width() if close_lbl.winfo_ismapped() else 20
|
||||||
|
avail = max(24, row.winfo_width() - close_w - 18 - 14)
|
||||||
|
font = tkfont.Font(font=name_lbl.cget("font"))
|
||||||
|
if font.measure(full) <= avail:
|
||||||
|
name_lbl.configure(text=full)
|
||||||
|
return
|
||||||
|
for i in range(len(full), 0, -1):
|
||||||
|
candidate = full[:i].rstrip() + "…"
|
||||||
|
if font.measure(candidate) <= avail:
|
||||||
|
name_lbl.configure(text=candidate)
|
||||||
|
return
|
||||||
|
name_lbl.configure(text="…")
|
||||||
|
|
||||||
|
def set_selected(selected: bool) -> None:
|
||||||
|
item["selected"] = selected
|
||||||
|
if selected:
|
||||||
|
close_lbl.pack(side=tk.RIGHT, padx=(0, 14))
|
||||||
|
else:
|
||||||
|
close_lbl.pack_forget()
|
||||||
|
_apply_style()
|
||||||
|
row.after_idle(_truncate_name)
|
||||||
|
|
||||||
|
def _on_click(_event=None) -> None:
|
||||||
|
command()
|
||||||
|
|
||||||
|
def _on_enter(_event=None) -> None:
|
||||||
|
if not item["selected"]:
|
||||||
|
item["hover"] = True
|
||||||
|
_apply_style()
|
||||||
|
|
||||||
|
def _on_leave(_event=None) -> None:
|
||||||
|
px, py = row.winfo_pointerxy()
|
||||||
|
rx, ry = row.winfo_rootx(), row.winfo_rooty()
|
||||||
|
rw, rh = row.winfo_width(), row.winfo_height()
|
||||||
|
if rx <= px < rx + rw and ry <= py < ry + rh:
|
||||||
|
return
|
||||||
|
item["hover"] = False
|
||||||
|
_apply_style()
|
||||||
|
|
||||||
|
def _on_configure(_event=None) -> None:
|
||||||
|
if item["selected"]:
|
||||||
|
_truncate_name()
|
||||||
|
|
||||||
|
for widget in (row, name_lbl, close_lbl):
|
||||||
|
widget.bind("<Button-1>", _on_click)
|
||||||
|
widget.bind("<Enter>", _on_enter)
|
||||||
|
widget.bind("<Leave>", _on_leave)
|
||||||
|
row.bind("<Configure>", _on_configure)
|
||||||
|
|
||||||
|
item["set_selected"] = set_selected
|
||||||
|
item["apply_theme"] = _apply_style
|
||||||
|
item["pack"] = lambda **kw: row.pack(fill=tk.X, padx=0, pady=1, **kw)
|
||||||
|
|
||||||
|
_apply_style()
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
def _set_tool_panel_sidebar_selected(
|
||||||
|
panel_info: dict[str, Any], selected: bool
|
||||||
|
) -> None:
|
||||||
|
sidebar_item = panel_info.get("sidebar_item")
|
||||||
|
if sidebar_item is not None:
|
||||||
|
sidebar_item["set_selected"](selected)
|
||||||
|
return
|
||||||
|
button = panel_info.get("button")
|
||||||
|
if button is not None:
|
||||||
|
button.configure(
|
||||||
|
style="SidebarSelected.TButton" if selected else "Sidebar.TButton"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_tool_panel_sidebar_theme(self: "PQAutomationApp") -> None:
|
||||||
|
"""主题切换后刷新工具面板侧栏项配色。"""
|
||||||
|
for panel_info in self.panels.values():
|
||||||
|
sidebar_item = panel_info.get("sidebar_item")
|
||||||
|
if sidebar_item is not None:
|
||||||
|
sidebar_item["apply_theme"]()
|
||||||
|
|
||||||
|
|
||||||
def register_panel(self: "PQAutomationApp", panel_name, frame, button, visible_attr):
|
def register_panel(self: "PQAutomationApp", panel_name, frame, button, visible_attr):
|
||||||
"""注册一个面板到管理系统"""
|
"""注册一个面板到管理系统"""
|
||||||
self.panels[panel_name] = {
|
self.panels[panel_name] = {
|
||||||
"frame": frame,
|
"frame": frame,
|
||||||
"button": button,
|
"button": button,
|
||||||
|
"button_label": None,
|
||||||
|
"sidebar_item": None,
|
||||||
"visible_attr": visible_attr,
|
"visible_attr": visible_attr,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +221,8 @@ def show_panel(self: "PQAutomationApp", panel_name):
|
|||||||
# 显示目标面板
|
# 显示目标面板
|
||||||
panel_info["frame"].pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=5, pady=5)
|
panel_info["frame"].pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=5, pady=5)
|
||||||
|
|
||||||
# 更新按钮样式
|
# 更新侧栏选中样式
|
||||||
if panel_info["button"]:
|
_set_tool_panel_sidebar_selected(panel_info, True)
|
||||||
panel_info["button"].configure(style="SidebarSelected.TButton")
|
|
||||||
|
|
||||||
# 更新状态
|
# 更新状态
|
||||||
setattr(self, panel_info["visible_attr"], True)
|
setattr(self, panel_info["visible_attr"], True)
|
||||||
@@ -80,8 +234,7 @@ def hide_all_panels(self: "PQAutomationApp"):
|
|||||||
# 隐藏所有注册的面板
|
# 隐藏所有注册的面板
|
||||||
for panel_name, panel_info in self.panels.items():
|
for panel_name, panel_info in self.panels.items():
|
||||||
panel_info["frame"].pack_forget()
|
panel_info["frame"].pack_forget()
|
||||||
if panel_info["button"]:
|
_set_tool_panel_sidebar_selected(panel_info, False)
|
||||||
panel_info["button"].configure(style="Sidebar.TButton")
|
|
||||||
setattr(self, panel_info["visible_attr"], False)
|
setattr(self, panel_info["visible_attr"], False)
|
||||||
|
|
||||||
# 显示主内容区域
|
# 显示主内容区域
|
||||||
@@ -110,6 +263,8 @@ class PanelManagerMixin:
|
|||||||
"""由 tools/refactor_to_mixins.py 自动生成。
|
"""由 tools/refactor_to_mixins.py 自动生成。
|
||||||
把本模块的自由函数挂到 PQAutomationApp 上,便于 F12 跳转与类型推断。
|
把本模块的自由函数挂到 PQAutomationApp 上,便于 F12 跳转与类型推断。
|
||||||
"""
|
"""
|
||||||
|
create_tool_panel_sidebar_item = create_tool_panel_sidebar_item
|
||||||
register_panel = register_panel
|
register_panel = register_panel
|
||||||
show_panel = show_panel
|
show_panel = show_panel
|
||||||
hide_all_panels = hide_all_panels
|
hide_all_panels = hide_all_panels
|
||||||
|
refresh_tool_panel_sidebar_theme = refresh_tool_panel_sidebar_theme
|
||||||
|
|||||||
@@ -774,21 +774,19 @@ def create_test_type_frame(self: "PQAutomationApp"):
|
|||||||
).pack(fill=tk.X, padx=16, pady=(16, 6), anchor="w")
|
).pack(fill=tk.X, padx=16, pady=(16, 6), anchor="w")
|
||||||
|
|
||||||
panel_buttons = [
|
panel_buttons = [
|
||||||
("ai_image_btn", "AI 图片", self.toggle_ai_image_panel),
|
("ai_image_btn", "ai_image", "AI 图片", self.toggle_ai_image_panel),
|
||||||
("pantone_baseline_btn", "Pantone 摸底", self.toggle_pantone_baseline_panel),
|
("pantone_baseline_btn", "pantone_baseline", "Pantone 摸底", self.toggle_pantone_baseline_panel),
|
||||||
("gamma_pattern_btn", "Gamma Pattern编辑", self.toggle_gamma_pattern_panel),
|
("gamma_pattern_btn", "gamma_pattern", "Gamma Pattern编辑", self.toggle_gamma_pattern_panel),
|
||||||
("calman_btn", "CALMAN 灰阶", self.toggle_calman_panel),
|
("calman_btn", "calman", "CALMAN 灰阶", self.toggle_calman_panel),
|
||||||
]
|
]
|
||||||
for attr, text, cmd in panel_buttons:
|
for attr, panel_name, text, cmd in panel_buttons:
|
||||||
btn = ttk.Button(
|
item = self.create_tool_panel_sidebar_item(self.sidebar_frame, text, cmd)
|
||||||
self.sidebar_frame,
|
item["pack"]()
|
||||||
text=text,
|
setattr(self, attr, item["row"])
|
||||||
style="Sidebar.TButton",
|
if hasattr(self, "panels") and panel_name in self.panels:
|
||||||
command=cmd,
|
self.panels[panel_name]["button_label"] = text
|
||||||
takefocus=False,
|
self.panels[panel_name]["sidebar_item"] = item
|
||||||
)
|
self.panels[panel_name]["button"] = item["row"]
|
||||||
btn.pack(fill=tk.X, padx=0, pady=1)
|
|
||||||
setattr(self, attr, btn)
|
|
||||||
|
|
||||||
# 测试版水印标签(版本 x.x.0.0 时显示)
|
# 测试版水印标签(版本 x.x.0.0 时显示)
|
||||||
from app_version import is_beta_version, APP_VERSION
|
from app_version import is_beta_version, APP_VERSION
|
||||||
@@ -822,7 +820,7 @@ def create_test_type_frame(self: "PQAutomationApp"):
|
|||||||
self.theme_toggle_btn.pack(fill=tk.X, padx=0, pady=(0, 2), side=tk.BOTTOM)
|
self.theme_toggle_btn.pack(fill=tk.X, padx=0, pady=(0, 2), side=tk.BOTTOM)
|
||||||
_refresh_theme_toggle_label(self)
|
_refresh_theme_toggle_label(self)
|
||||||
|
|
||||||
# 注册面板按钮
|
# 注册面板侧栏按钮
|
||||||
if hasattr(self, "panels"):
|
if hasattr(self, "panels"):
|
||||||
if "ai_image" in self.panels:
|
if "ai_image" in self.panels:
|
||||||
self.panels["ai_image"]["button"] = self.ai_image_btn
|
self.panels["ai_image"]["button"] = self.ai_image_btn
|
||||||
@@ -862,6 +860,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_tool_panel_sidebar_theme"):
|
||||||
|
try:
|
||||||
|
self.refresh_tool_panel_sidebar_theme()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
if hasattr(self, "refresh_connection_indicators"):
|
if hasattr(self, "refresh_connection_indicators"):
|
||||||
try:
|
try:
|
||||||
self.refresh_connection_indicators()
|
self.refresh_connection_indicators()
|
||||||
|
|||||||
@@ -105,5 +105,9 @@
|
|||||||
"measurement_bit_depth": 8,
|
"measurement_bit_depth": 8,
|
||||||
"measurement_max_value": 0,
|
"measurement_max_value": 0,
|
||||||
"pattern_params": []
|
"pattern_params": []
|
||||||
|
},
|
||||||
|
"acquisition_timing": {
|
||||||
|
"pattern_settle_time": 0.4,
|
||||||
|
"pattern_progress_log_step": 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user