From 69a6dc892a584fa1af51b268f1fcc376f3c0f562 Mon Sep 17 00:00:00 2001 From: ila Date: Tue, 16 Jun 2026 15:39:45 +0800 Subject: [PATCH] fix: keep print and re-apply selected template on preview switch Switching the preview garment cleared the scene (print lost), and re-loading a print used the canvas's hard-coded centred default instead of the selected template. - template_panel: add apply_current() to re-emit the selected template for the current garment/print sizes and sync _current_state. - main_window: remember the current print path, restore it after a garment switch, and call apply_current() after garment/print changes so the selected template stays sticky. Fine-tuned items are unaffected. - Also feed template_applied into export_panel.set_transform to keep the single-export transform in sync. Docs: record the sticky-template rule (PRD 6.6). Co-Authored-By: Claude Opus 4.8 --- docs/02-prd.md | 1 + src/app/main_window.py | 34 ++++++++++++++++++++++--------- src/app/widgets/template_panel.py | 13 ++++++++++++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/docs/02-prd.md b/docs/02-prd.md index b5ec978..2997e00 100644 --- a/docs/02-prd.md +++ b/docs/02-prd.md @@ -163,6 +163,7 @@ - 模板参数应基于衣服底图尺寸计算,避免只适配单一图片分辨率。 - 模板的 `width_ratio` / `height_ratio` 定义衣服上的**目标框**,而非强制拉伸尺寸。已知印花原始尺寸时,印花按自身宽高比缩放后 contain 进目标框并居中,不被拉伸变形;未知印花尺寸时退化为铺满目标框。 - 内置模板尺寸以贴近真实印花占比为准(例如正方形模板约为衣服宽度的 1/3),避免印花占据过大面积。 +- 选中的模板是**粘性**的:在预览区切换衣服或切换印花时,印花不应丢失,应按当前选中模板基于新的衣服/印花尺寸重新计算落位,而非回退到画布的写死默认值。已手动微调的项不受影响,仍使用其自身参数。 ### 6.7 自定义模板 diff --git a/src/app/main_window.py b/src/app/main_window.py index ea5c383..79cf9a1 100644 --- a/src/app/main_window.py +++ b/src/app/main_window.py @@ -50,6 +50,7 @@ class MainWindow(QMainWindow): # Fine-tune state: track which queue item is currently being edited self._active_queue_item = None self._loading_queue_item = False # suppress fine-tune marking during item load + self._current_print_path = None # keep the print across garment switches root = QWidget() root.setObjectName("root") @@ -277,11 +278,23 @@ class MainWindow(QMainWindow): self.template_panel.template_applied.connect(self.image_canvas.set_transform) self.template_panel.template_applied.connect(self.transform_panel.set_transform) self.template_panel.template_applied.connect(self.queue_panel.set_transform) + self.template_panel.template_applied.connect(self.export_panel.set_transform) # ── Export panel secondary buttons → template panel ──────────────── self.export_panel.apply_as_template.connect(self.template_panel._save_as_template) self.export_panel.reset_to_template.connect(self.template_panel._reset_to_template) + def _load_print_preview(self, path): + """Load a print into the canvas and sync its native size to the template panel.""" + self.image_canvas.load_print(path) + self.export_panel.set_print(path) + try: + from PIL import Image as _PilImage + with _PilImage.open(path) as img: + self.template_panel.set_print_size(img.width, img.height) + except Exception: + pass + def _on_garment_preview(self, asset): """Load a garment from the asset list into the canvas for direct preview.""" self._active_queue_item = None # leave queue mode @@ -298,23 +311,24 @@ class MainWindow(QMainWindow): self.template_panel.set_garment_size(img.width, img.height) except Exception: pass + # load_garment clears the scene; restore the current print and re-lay it + # out with the selected template (instead of the canvas default). + if self._current_print_path: + self._load_print_preview(self._current_print_path) + self.template_panel.apply_current() def _on_print_preview(self, asset): """Load a print from the asset list into the canvas for direct preview.""" self._active_queue_item = None if not asset: + self._current_print_path = None self.export_panel.set_print(None) return - path = str(asset.path) - self.image_canvas.load_print(path) - self.export_panel.set_print(path) - # Tell template panel the print dimensions for aspect-aware fitting - try: - from PIL import Image as _PilImage - with _PilImage.open(path) as img: - self.template_panel.set_print_size(img.width, img.height) - except Exception: - pass + self._current_print_path = str(asset.path) + self._load_print_preview(self._current_print_path) + # Apply the selected template so the print lands per the chosen layout, + # not the canvas's hard-coded centred default. + self.template_panel.apply_current() def _on_queue_item_activated(self, item): """Load a queue item into the canvas and arm fine-tune tracking.""" diff --git a/src/app/widgets/template_panel.py b/src/app/widgets/template_panel.py index e13cb84..7487640 100644 --- a/src/app/widgets/template_panel.py +++ b/src/app/widgets/template_panel.py @@ -138,6 +138,19 @@ class TemplatePanel(QWidget): self._print_w or None, self._print_h or None, ) + def apply_current(self): + """Re-apply the currently selected template using current garment/print sizes. + + Lets the selected template stay 'sticky': callers invoke this after the + preview garment or print changes so the layout is recomputed from the + template instead of falling back to the canvas default. + """ + t = self._current_template() + if t and self._garment_w > 0 and self._garment_h > 0: + state = self._state_for_template(t) + self._current_state = state + self.template_applied.emit(state) + def set_transform(self, state: TransformState): """Store current print transform (used when saving a template).""" self._current_state = state