95 lines
3.4 KiB
Python
95 lines
3.4 KiB
Python
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 |