搅拌桨旋转(目前上料斗左移到搅拌楼下时触发)

This commit is contained in:
2025-11-06 19:03:56 +08:00
parent 75df5d79ef
commit 2b93713e7f
2 changed files with 144 additions and 28 deletions

View File

@ -197,6 +197,8 @@ class MainWindow(QWidget):
# 以下为模拟:
# 假设两秒种之后,移动到了搅拌机下 (这里需要根据实际情况修改)
QTimer.singleShot(2000, self.conveyor_system_widget.moveHopperBelowMixer)
# 移动到搅拌楼下,搅拌桨就开始旋转
QTimer.singleShot(2100, self.mixer_widget.startBladeMix)
# 料斗左移完成,恢复料斗右移按钮
QTimer.singleShot(2100, lambda: self.conveyor_system_widget.right_btn.setEnabled(True))
@ -205,8 +207,12 @@ class MainWindow(QWidget):
# 演示效果
self.conveyor_system_widget.moveHopperToTransition() # 移动到过渡的位置
self.hopper_widget.upper_clamp_widget.set_angle(0) # 上料斗向右移动到目的地时夹爪的角度一定是0
# 按钮状态:点击料斗右移按钮后,禁用料斗左移按钮
# 按钮状态:点击料斗右移按钮后,禁用料斗左移按钮
self.conveyor_system_widget.left_btn.setEnabled(False)
# 开始右移,搅拌桨就停止转动
self.mixer_widget.stopBladeMix()
# 以下为模拟:
# 假设两秒后,传送带中 料斗向右移动完成 (这里需要根据实际情况修改)
QTimer.singleShot(1900, self.conveyor_system_widget.hideHopper) # 料斗向右移动完成,隐藏料斗

View File

@ -1,14 +1,88 @@
from PySide6.QtWidgets import QWidget, QLabel, QHBoxLayout
from PySide6.QtGui import QPixmap, QFont
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap, QFont, QTransform
from PySide6.QtCore import Qt, QPropertyAnimation, QEasingCurve, Property
import resources.resources_rc
from utils.image_paths import ImagePaths
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())
class MixerWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
# 两个搅拌桨的转动的动画引用
self.animations = [] # 保存动画引用
# 初始化布局
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
@ -28,35 +102,71 @@ class MixerWidget(QWidget):
""")
layout.addWidget(self.text_label, alignment=Qt.AlignLeft)
# 2. 创建搅拌机设备及搅拌桨图标
# 2. 创建搅拌机设备
self.device_label = QLabel()
device_pixmap = QPixmap(ImagePaths.MIXER)
self.device_label.setPixmap(device_pixmap)
layout.addWidget(self.device_label, alignment=Qt.AlignLeft)
# 3. 叠加两个搅拌桨图标
self.blade1 = QLabel(self.device_label) # 从左往右第一个搅拌桨
blade1_pixmap = QPixmap(ImagePaths.MIXER_PADDLE)
self.blade1.setPixmap(blade1_pixmap)
self.blade1.move(
(device_pixmap.width() - blade1_pixmap.width()) // 2 - 26,
(device_pixmap.height() - blade1_pixmap.height()) // 2 - 4
)
# 3. 初始化两个搅拌桨
self._init_blades()
self.blade2 = QLabel(self.device_label)
blade2_pixmap = QPixmap(ImagePaths.MIXER_PADDLE) # 从左往右第二个搅拌桨
self.blade2.setPixmap(blade2_pixmap)
self.blade2.move(
(device_pixmap.width() - blade2_pixmap.width()) // 2 + 31,
(device_pixmap.height() - blade2_pixmap.height()) // 2 - 4
)
def _init_blades(self):
blade_pixmap = QPixmap(ImagePaths.MIXER_PADDLE)
if blade_pixmap.isNull():
return
# 测试代码
if __name__ == "__main__":
import sys
from PySide6.QtWidgets import QApplication, QMainWindow
# 设备背景的尺寸(用于计算固定中心点)
device_pixmap = self.device_label.pixmap()
if not device_pixmap:
return
device_w = device_pixmap.width()
device_h = device_pixmap.height()
app = QApplication(sys.argv)
mixer_widget = MixerWidget()
mixer_widget.show()
sys.exit(app.exec())
# --------------------------
# 左搅拌桨:计算固定中心点
# --------------------------
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):
self.animations.clear()
# 备注duration控制搅拌桨旋转的速度值越小旋转得越快
self._start_animation(self.blade1, duration)
self._start_animation(self.blade2, duration)
def stopBladeMix(self):
for animation in self.animations:
animation.stop()
if self.blade1:
self.blade1.reset_to_original()
if self.blade2:
self.blade2.reset_to_original()