Files
Feeding_control_system/view/widgets/mixer_widget.py

186 lines
7.8 KiB
Python
Raw Normal View History

2025-10-31 18:52:31 +08:00
from PySide6.QtWidgets import QWidget, QLabel, QHBoxLayout
from PySide6.QtGui import QPixmap, QFont, QTransform
from PySide6.QtCore import Qt, QPropertyAnimation, QEasingCurve, Property
2025-10-31 18:52:31 +08:00
import resources.resources_rc
2025-11-01 16:13:14 +08:00
from utils.image_paths import ImagePaths
2025-10-31 18:52:31 +08:00
class BladeLabel(QLabel):
def __init__(self, parent=None):
super().__init__(parent)
self._rotation = 0.0
self._original_pixmap = None
self._original_center_x = 0.0 # 原始图片自身中心点x
self._original_center_y = 0.0 # 原始图片自身中心点y
self._fixed_center_in_parent_x = 0 # 父容器中的固定中心点x关键
self._fixed_center_in_parent_y = 0 # 父容器中的固定中心点y关键
# self.setFixedSize(50, 54)
def set_original_pixmap(self, pixmap, fixed_center_x, fixed_center_y):
"""
:param pixmap: 原始图片
:param fixed_center_x: 父容器中固定的中心点x坐标绝对位置
:param fixed_center_y: 父容器中固定的中心点y坐标绝对位置
"""
self._original_pixmap = pixmap
if pixmap.isNull():
print("错误:搅拌桨图片加载失败!")
return
# 记录原始图片自身的中心点(用于旋转计算)
self._original_center_x = 28 # 图片的中心点为 28,28
self._original_center_y = 28
# 记录在父容器中的固定中心点(旋转时始终对齐这个点)
self._fixed_center_in_parent_x = fixed_center_x
self._fixed_center_in_parent_y = fixed_center_y
# 初始显示图片
self.setPixmap(pixmap)
# 初始位置:让原始图片的中心点与固定中心点对齐
self._update_position(pixmap.width(), pixmap.height())
def _update_position(self, current_w, current_h):
"""根据当前图片尺寸,计算位置使中心点与固定坐标对齐"""
# 当前图片的中心点坐标(自身坐标系)
current_center_x = current_w / 2
current_center_y = current_h / 2
# 计算左上角坐标:固定中心点 - 当前图片中心点
x = self._fixed_center_in_parent_x - current_center_x
y = self._fixed_center_in_parent_y - current_center_y
self.move(round(x), round(y)) # 取整避免浮点数位置偏差
self.setFixedSize(current_w, current_h)
def get_rotation(self):
return self._rotation
def set_rotation(self, angle):
self._rotation = angle
if self._original_pixmap is None:
return
# 生成旋转后的图片(保持旋转中心为原始图片中心)
transform = QTransform()
transform.translate(self._original_center_x, self._original_center_y)
transform.rotate(angle)
transform.translate(-self._original_center_x, -self._original_center_y)
rotated_pixmap = self._original_pixmap.transformed(transform, Qt.SmoothTransformation)
# 强制对齐固定中心点(关键:无论尺寸如何变化,中心点不变)
self._update_position(rotated_pixmap.width(), rotated_pixmap.height())
self.setPixmap(rotated_pixmap)
rotation = Property(float, get_rotation, set_rotation)
def reset_to_original(self):
self._rotation = 0.0 # 重置旋转角度为0°
if self._original_pixmap is not None:
self.setPixmap(self._original_pixmap) # 恢复原始图片
# 恢复初始位置(基于原始图片尺寸)
self._update_position(self._original_pixmap.width(), self._original_pixmap.height())
2025-10-31 18:52:31 +08:00
class MixerWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
2026-01-11 18:00:32 +08:00
# 状态变量:标记搅拌桨是否正在旋转
self.is_mixing = False # 初始状态为未旋转
# 两个搅拌桨的转动的动画引用
self.animations = [] # 保存动画引用
2025-10-31 18:52:31 +08:00
# 初始化布局
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
self.setFixedSize(225, 102)
# 1. 创建“搅拌机”文字标签
self.text_label = QLabel("搅拌机")
self.text_label.setFixedSize(100, 23)
self.text_label.setFont(QFont("Arial", 14)) # 设置字体大小为16px
self.text_label.setAlignment(Qt.AlignCenter)
2025-11-01 16:13:14 +08:00
self.text_label.setStyleSheet(f"""
background-image: url({ImagePaths.TEXT_TITLE_BG});
2025-10-31 18:52:31 +08:00
background-repeat: no-repeat;
background-position: center;
color: #0bffff; /* 可根据需求调整文字颜色 */
""")
layout.addWidget(self.text_label, alignment=Qt.AlignLeft)
# 2. 创建搅拌机设备
2025-10-31 18:52:31 +08:00
self.device_label = QLabel()
2025-11-01 16:13:14 +08:00
device_pixmap = QPixmap(ImagePaths.MIXER)
2025-10-31 18:52:31 +08:00
self.device_label.setPixmap(device_pixmap)
layout.addWidget(self.device_label, alignment=Qt.AlignLeft)
# 3. 初始化两个搅拌桨
self._init_blades()
def _init_blades(self):
blade_pixmap = QPixmap(ImagePaths.MIXER_PADDLE)
if blade_pixmap.isNull():
return
# 设备背景的尺寸(用于计算固定中心点)
device_pixmap = self.device_label.pixmap()
if not device_pixmap:
return
device_w = device_pixmap.width()
device_h = device_pixmap.height()
# --------------------------
# 左搅拌桨:计算固定中心点
# --------------------------
left_center_x = (device_w // 2) - 26 # 左桨中心点x示例值需根据实际调整
left_center_y = device_h // 2 - 5 # 左桨中心点y示例值需根据实际调整
self.blade1 = BladeLabel(self.device_label)
self.blade1.set_original_pixmap(blade_pixmap, left_center_x, left_center_y)
# --------------------------
# 右搅拌桨:计算固定中心点
# --------------------------
right_center_x = (device_w // 2) + 30 # 右桨中心点x示例值需根据实际调整
right_center_y = device_h // 2 - 5 # 右桨中心点y与左桨对齐
self.blade2 = BladeLabel(self.device_label)
self.blade2.set_original_pixmap(blade_pixmap, right_center_x, right_center_y)
def _start_animation(self, blade: BladeLabel, duration: int, reverse: bool = False):
"""
Args:
blade: 所需旋转的搅拌桨标签
duration 一次搅拌桨旋转所需的时间值越小旋转越快
reverse: 是否反转逆时针转
"""
animation = QPropertyAnimation(blade, b"rotation")
animation.setStartValue(360 if reverse else 0)
animation.setEndValue(0 if reverse else 360)
animation.setDuration(duration)
animation.setEasingCurve(QEasingCurve.Linear)
animation.setLoopCount(-1)
self.animations.append(animation)
animation.start()
# 搅拌桨开始搅拌
def startBladeMix(self, duration=700):
2026-01-11 18:00:32 +08:00
if self.is_mixing: # 搅拌桨已经在旋转
return
self.animations.clear()
# 备注duration控制搅拌桨旋转的速度值越小旋转得越快
self._start_animation(self.blade1, duration)
self._start_animation(self.blade2, duration)
2026-01-11 18:00:32 +08:00
self.is_mixing = True # 更新搅拌桨状态为旋转中
def stopBladeMix(self):
2026-01-11 18:00:32 +08:00
if not self.is_mixing: # 搅拌桨已经停止
return
for animation in self.animations:
animation.stop()
if self.blade1:
self.blade1.reset_to_original()
if self.blade2:
self.blade2.reset_to_original()
2026-01-11 18:00:32 +08:00
self.is_mixing = False # 更新搅拌桨状态为停止