ui更新
This commit is contained in:
parent
f8c60f0aa4
commit
792f296bdc
|
|
@ -6,8 +6,8 @@
|
||||||
界面结构(结算机)::
|
界面结构(结算机)::
|
||||||
|
|
||||||
┌ 顶栏:标题 + 状态徽章 + 设置 ─────────────────────┐
|
┌ 顶栏:标题 + 状态徽章 + 设置 ─────────────────────┐
|
||||||
├ 左:已点菜品清单 ─────────┬─ 右:绿提示 + 大预览 ─┤
|
├ 左:识别图 + 已点清单 ─────┬─ 右:绿提示 + 大预览 ─┤
|
||||||
│ 缩略图 / 菜名 / 数量 │ │ 流畅预览 + 识别框叠加 │
|
│ 识别整图 / 菜名 / 数量 │ │ 流畅预览 + 识别框叠加 │
|
||||||
├──────────────────────────┴───────────────────────┤
|
├──────────────────────────┴───────────────────────┤
|
||||||
│ 底栏:暂停/继续扫描|选图识别|清空|设置 │
|
│ 底栏:暂停/继续扫描|选图识别|清空|设置 │
|
||||||
└──────────────────────────────────────────────────┘
|
└──────────────────────────────────────────────────┘
|
||||||
|
|
@ -111,6 +111,8 @@ class BaseDishApp(PendingLearningUIMixin):
|
||||||
self._dock_thumb_refs = []
|
self._dock_thumb_refs = []
|
||||||
self._cart = []
|
self._cart = []
|
||||||
self._cart_thumbs = []
|
self._cart_thumbs = []
|
||||||
|
self._cart_result_image = None # 左侧已点区展示的识别整图路径
|
||||||
|
self._cart_result_photo = None
|
||||||
self._template_filter = ""
|
self._template_filter = ""
|
||||||
self._template_page = 0
|
self._template_page = 0
|
||||||
self._template_page_size = 40 # 大库分页,避免一次渲染上千行闪退
|
self._template_page_size = 40 # 大库分页,避免一次渲染上千行闪退
|
||||||
|
|
@ -1317,6 +1319,23 @@ class BaseDishApp(PendingLearningUIMixin):
|
||||||
font=FONTS["small"])
|
font=FONTS["small"])
|
||||||
self.cart_count_label.pack(side=tk.RIGHT)
|
self.cart_count_label.pack(side=tk.RIGHT)
|
||||||
|
|
||||||
|
# 识别整图:放在清单上方空白区
|
||||||
|
img_wrap = tk.Frame(
|
||||||
|
panel, bg=c["pos_row_alt"],
|
||||||
|
highlightbackground=c["border"], highlightthickness=1,
|
||||||
|
height=168,
|
||||||
|
)
|
||||||
|
img_wrap.pack(fill=tk.X, padx=8, pady=(0, 8))
|
||||||
|
img_wrap.pack_propagate(False)
|
||||||
|
self.cart_result_label = tk.Label(
|
||||||
|
img_wrap,
|
||||||
|
text="识别图片将显示在这里",
|
||||||
|
bg=c["pos_row_alt"], fg=c["muted"],
|
||||||
|
font=FONTS["small"],
|
||||||
|
compound=tk.CENTER,
|
||||||
|
)
|
||||||
|
self.cart_result_label.pack(fill=tk.BOTH, expand=True, padx=2, pady=2)
|
||||||
|
|
||||||
cols = tk.Frame(panel, bg=c["pos_row_alt"])
|
cols = tk.Frame(panel, bg=c["pos_row_alt"])
|
||||||
cols.pack(fill=tk.X)
|
cols.pack(fill=tk.X)
|
||||||
for text, w in (("菜品", 22), ("数量", 10), ("", 4)):
|
for text, w in (("菜品", 22), ("数量", 10), ("", 4)):
|
||||||
|
|
@ -2546,11 +2565,12 @@ class BaseDishApp(PendingLearningUIMixin):
|
||||||
written=pending_written, elapsed=stable_elapsed,
|
written=pending_written, elapsed=stable_elapsed,
|
||||||
committed=already_committed, hold_s=hold,
|
committed=already_committed, hold_s=hold,
|
||||||
same_order=order_unchanged,
|
same_order=order_unchanged,
|
||||||
|
frame_ref=frame,
|
||||||
):
|
):
|
||||||
# 只更新叠加框 + 左侧清单;预览继续刷实时帧
|
# 只更新叠加框 + 左侧清单;预览继续刷实时帧
|
||||||
self._live_overlay_dishes = list(ds or [])
|
self._live_overlay_dishes = list(ds or [])
|
||||||
# 菜品未变:仍刷新预览框,但左侧保持/同步同一批菜,不视为新单
|
# 有已识别菜时更新左侧识别整图(新单用存盘图,否则用当前帧)
|
||||||
self.render_result_dock(ds, path)
|
self.render_result_dock(ds, path, frame_bgr=frame_ref)
|
||||||
try:
|
try:
|
||||||
self.update_pending_btn()
|
self.update_pending_btn()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
@ -2578,9 +2598,9 @@ class BaseDishApp(PendingLearningUIMixin):
|
||||||
)
|
)
|
||||||
|
|
||||||
if written:
|
if written:
|
||||||
self._toast(f"已记入待学习 {written} 个未知菜", "warn")
|
self._toast(f"已记入待学习并上报 {written} 个未知菜", "warn")
|
||||||
self._set_result_text(
|
self._set_result_text(
|
||||||
f"未知菜已记入待学习({written})|左侧仅显示已识别",
|
f"未知菜已记入待学习并上报({written})|左侧仅显示已识别",
|
||||||
"warn",
|
"warn",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -2626,6 +2646,8 @@ class BaseDishApp(PendingLearningUIMixin):
|
||||||
self._last_dishes = []
|
self._last_dishes = []
|
||||||
self._live_overlay_dishes = []
|
self._live_overlay_dishes = []
|
||||||
self._reset_order_gate()
|
self._reset_order_gate()
|
||||||
|
self._cart_result_image = None
|
||||||
|
self._render_cart_result_image()
|
||||||
self.render_cart()
|
self.render_cart()
|
||||||
if not self._preview_enabled and not self._live_enabled and hasattr(self, "img_label"):
|
if not self._preview_enabled and not self._live_enabled and hasattr(self, "img_label"):
|
||||||
self.img_label.config(
|
self.img_label.config(
|
||||||
|
|
@ -2635,6 +2657,74 @@ class BaseDishApp(PendingLearningUIMixin):
|
||||||
self.img_label.image = None
|
self.img_label.image = None
|
||||||
self._set_result_text("已清空本次已点菜品", "ok")
|
self._set_result_text("已清空本次已点菜品", "ok")
|
||||||
|
|
||||||
|
def _set_cart_result_image(self, image_path=None, frame_bgr=None, dishes=None):
|
||||||
|
"""更新左侧已点区识别整图;优先磁盘路径,否则用内存帧(可叠识别框)。"""
|
||||||
|
if image_path and os.path.exists(str(image_path)):
|
||||||
|
self._cart_result_image = os.path.abspath(str(image_path))
|
||||||
|
self._render_cart_result_image()
|
||||||
|
return
|
||||||
|
if frame_bgr is not None:
|
||||||
|
try:
|
||||||
|
os.makedirs("images", exist_ok=True)
|
||||||
|
path = os.path.abspath(os.path.join("images", "_cart_result_preview.jpg"))
|
||||||
|
saved = False
|
||||||
|
if dishes:
|
||||||
|
try:
|
||||||
|
rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
|
||||||
|
im = Image.fromarray(rgb)
|
||||||
|
im = self._draw_live_overlay_pil(im, dishes)
|
||||||
|
im.convert("RGB").save(path, quality=88)
|
||||||
|
saved = os.path.isfile(path)
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"[cart] overlay preview failed: {exc}")
|
||||||
|
if not saved:
|
||||||
|
saved = bool(cv2.imwrite(path, frame_bgr))
|
||||||
|
if saved:
|
||||||
|
self._cart_result_image = path
|
||||||
|
self._render_cart_result_image()
|
||||||
|
return
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"[cart] preview from frame failed: {exc}")
|
||||||
|
# 无新图则保持当前展示
|
||||||
|
|
||||||
|
def _render_cart_result_image(self):
|
||||||
|
if not hasattr(self, "cart_result_label"):
|
||||||
|
return
|
||||||
|
path = getattr(self, "_cart_result_image", None)
|
||||||
|
c = COLORS
|
||||||
|
if not path or not os.path.exists(str(path)):
|
||||||
|
self.cart_result_label.config(
|
||||||
|
text="识别图片将显示在这里", image="",
|
||||||
|
bg=c["pos_row_alt"], fg=c["muted"],
|
||||||
|
)
|
||||||
|
self._cart_result_photo = None
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
im = Image.open(f).convert("RGB")
|
||||||
|
max_w, max_h = 300, 156
|
||||||
|
try:
|
||||||
|
w = max(self.cart_result_label.winfo_width(), 120)
|
||||||
|
if w > 40:
|
||||||
|
max_w = min(w - 8, 360)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
resample = Image.Resampling.LANCZOS
|
||||||
|
except Exception:
|
||||||
|
resample = Image.LANCZOS
|
||||||
|
im.thumbnail((max_w, max_h), resample)
|
||||||
|
photo = ImageTk.PhotoImage(im)
|
||||||
|
self._cart_result_photo = photo
|
||||||
|
self.cart_result_label.config(text="", image=photo, bg=c["surface"])
|
||||||
|
except Exception as exc:
|
||||||
|
print(f"[cart] render result image failed: {exc}")
|
||||||
|
self.cart_result_label.config(
|
||||||
|
text="识别图片加载失败", image="",
|
||||||
|
bg=c["pos_row_alt"], fg=c["muted"],
|
||||||
|
)
|
||||||
|
self._cart_result_photo = None
|
||||||
|
|
||||||
def fill_cart_from_dishes(self, dishes):
|
def fill_cart_from_dishes(self, dishes):
|
||||||
"""左侧清单只放已识别菜;未知仅留在预览标注 / 待学习流程。
|
"""左侧清单只放已识别菜;未知仅留在预览标注 / 待学习流程。
|
||||||
|
|
||||||
|
|
@ -2738,8 +2828,13 @@ class BaseDishApp(PendingLearningUIMixin):
|
||||||
if hasattr(self, "cart_count_label"):
|
if hasattr(self, "cart_count_label"):
|
||||||
self.cart_count_label.config(text=f"{len(self._cart)} 项")
|
self.cart_count_label.config(text=f"{len(self._cart)} 项")
|
||||||
|
|
||||||
def render_result_dock(self, dishes, labeled_path=None):
|
def render_result_dock(self, dishes, labeled_path=None, frame_bgr=None):
|
||||||
"""兼容旧调用:识别结果写入购物车。"""
|
"""识别结果写入购物车,并刷新左侧识别整图。"""
|
||||||
|
known = [d for d in (dishes or []) if not d.get("is_unknown")]
|
||||||
|
if known:
|
||||||
|
self._set_cart_result_image(
|
||||||
|
labeled_path, frame_bgr=frame_bgr, dishes=dishes,
|
||||||
|
)
|
||||||
self.fill_cart_from_dishes(dishes)
|
self.fill_cart_from_dishes(dishes)
|
||||||
self.render_cart()
|
self.render_cart()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue