From 4997d71f72b8853ecacae72efb06cbc725d50343 Mon Sep 17 00:00:00 2001 From: Yorusora Date: Mon, 23 Feb 2026 17:51:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E9=AA=8C=E6=80=A7=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=A2=9E=E4=BA=86<=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=A2=84=E5=A4=84=E7=90=86>=E4=BD=BF=E7=94=A8vispy=E7=BB=98?= =?UTF-8?q?=E5=9B=BE=E6=97=B6=E7=9A=84=E5=8F=82=E8=80=83=E5=9B=BE=E4=BE=8B?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- func/Module_preprocess.py | 19 +++++++ func/utils/FloatingImagePanel.py | 95 +++++++++++++++++++++++++++++++ image/legend_preprocess.png | Bin 0 -> 4530 bytes 3 files changed, 114 insertions(+) create mode 100644 func/utils/FloatingImagePanel.py create mode 100644 image/legend_preprocess.png diff --git a/func/Module_preprocess.py b/func/Module_preprocess.py index bb96559..7652406 100644 --- a/func/Module_preprocess.py +++ b/func/Module_preprocess.py @@ -20,6 +20,7 @@ from func.utils.PublicFunc import PublicFunc from func.utils.Constants import Constants from func.Filters.Preprocessing import Butterworth_for_BCG_PreProcess, Butterworth_for_ECG_PreProcess from func.utils.Result import Result +from func.utils.FloatingImagePanel import add_floating_image_panel from ui.MainWindow.MainWindow_preprocess import Ui_MainWindow_preprocess from ui.setting.preprocess_input_setting import Ui_MainWindow_preprocess_input_setting @@ -187,6 +188,12 @@ class MainWindow_preprocess(QMainWindow): self.progressbar = None PublicFunc.add_progressbar(self) + self.image_overlay = add_floating_image_panel( + self.centralWidget(), + title="参考图例", + img_path=r"image\legend_preprocess.png" + ) + self.plot_mode = plot_mode if self.plot_mode == "matplotlib": #初始化画框 @@ -492,6 +499,18 @@ class MainWindow_preprocess(QMainWindow): self.ax0.grid(True) self.ax0.xaxis.set_major_formatter(Params.FORMATTER) + def update_overlay_position(self): + """手动定位函数""" + margin = 20 + x = self.width() - self.image_overlay.width() - margin + y = margin + self.image_overlay.move(x, y) + + def resizeEvent(self, event): + """确保窗口变大小时,悬浮窗依然在右上角""" + super().resizeEvent(event) + self.update_overlay_position() + class Data: diff --git a/func/utils/FloatingImagePanel.py b/func/utils/FloatingImagePanel.py new file mode 100644 index 0000000..4a0862b --- /dev/null +++ b/func/utils/FloatingImagePanel.py @@ -0,0 +1,95 @@ +from PySide6 import QtWidgets, QtCore, QtGui + + +class FloatingImagePanel(QtWidgets.QWidget): + def __init__(self, parent, title="原始比例预览", image_path=None): + super().__init__(parent) + self.is_expanded = True + + # 1. 样式配置 (保持深色风格,方便看清信号) + self.setAttribute(QtCore.Qt.WA_StyledBackground, True) + self.setStyleSheet(""" + FloatingImagePanel { + background-color: rgba(30, 30, 30, 220); + border: 2px solid #444; + border-radius: 4px; + } + QLabel#title_label { color: #ffffff; font-weight: bold; font-family: 'Consolas'; } + QPushButton#toggle_btn { background: #444; color: white; border: none; } + """) + + # 2. 布局初始化 + self.main_layout = QtWidgets.QVBoxLayout(self) + self.main_layout.setContentsMargins(4, 4, 4, 4) + self.main_layout.setSpacing(2) + + # --- 标题栏 --- + self.header = QtWidgets.QWidget() + header_layout = QtWidgets.QHBoxLayout(self.header) + header_layout.setContentsMargins(2, 2, 2, 2) + + self.title_label = QtWidgets.QLabel(title) + self.title_label.setObjectName("title_label") + self.toggle_btn = QtWidgets.QPushButton("▲") + self.toggle_btn.setFixedSize(22, 22) + + header_layout.addWidget(self.title_label) + header_layout.addStretch() + header_layout.addWidget(self.toggle_btn) + self.main_layout.addWidget(self.header) + + # --- 图片展示区 --- + self.image_label = QtWidgets.QLabel() + # 关键点 1:关闭自动填充,确保我们手动控制尺寸 + self.image_label.setScaledContents(False) + # 关键点 2:设置对齐方式为中心 + self.image_label.setAlignment(QtCore.Qt.AlignCenter) + self.main_layout.addWidget(self.image_label) + + # 3. 信号绑定 + self.toggle_btn.clicked.connect(self.toggle_content) + + # 4. 加载图片 + if image_path: + self.update_image(image_path) + + def update_image(self, path): + """完全根据图片的物理尺寸调整窗口""" + pixmap = QtGui.QPixmap(path) + if not pixmap.isNull(): + # 拿到图片的原始宽高 + w = pixmap.width() + h = pixmap.height() + + # 强制 Label 等于图片大小 + self.image_label.setFixedSize(w, h) + self.image_label.setPixmap(pixmap) + + # 让整个窗口重新计算布局,贴合 Label + self.adjustSize() + + # 保持展开状态 + self.set_expanded(True) + + def set_expanded(self, expanded: bool): + self.is_expanded = expanded + self.image_label.setVisible(expanded) + self.toggle_btn.setText("▲" if expanded else "▼") + + # 关键点 3:重置窗口大小 + # 展开时它会变大包住图片,收起时它会缩成标题栏大小 + self.adjustSize() + + # 通知父窗口刷新位置,防止因为变大而超出右边界 + if hasattr(self.parent(), 'update_overlay_position'): + self.parent().update_overlay_position() + + def toggle_content(self): + self.set_expanded(not self.is_expanded) + + +# --- 封装的调用函数 --- +def add_floating_image_panel(parent_widget, title="图片原尺寸", img_path=None): + panel = FloatingImagePanel(parent_widget, title, img_path) + panel.raise_() + return panel \ No newline at end of file diff --git a/image/legend_preprocess.png b/image/legend_preprocess.png new file mode 100644 index 0000000000000000000000000000000000000000..ee697f4e3ffa2fe9e47ce7f83a8468cf35e81259 GIT binary patch literal 4530 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 J6<;N0|0nx!L`47q literal 0 HcmV?d00001