PyQt5鼠标悬浮控件缩放:自定义缩放原点的实现疑问
解决PyQt5控件自定义缩放原点的问题
不需要使用特定类,只需要在缩放动画的同时调整控件的位置,就能实现围绕自定义原点(如右上、左下、顶部中心等)的缩放效果。核心思路是:缩放时根据目标原点计算控件位置的偏移量,同步动画控件的尺寸和位置,让指定原点保持不动。
修改后的实现代码
from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * # 定义缩放原点选项 class ScaleOrigin: TopLeft = 0 TopCenter = 1 TopRight = 2 BottomLeft = 3 BottomCenter = 4 BottomRight = 5 class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setFixedSize(600, 600) widget = QWidget() self.setCentralWidget(widget) layout = QVBoxLayout() widget.setLayout(layout) # 示例:创建不同缩放原点的控件 items = [ ("顶部中心", ScaleOrigin.TopCenter), ("右上", ScaleOrigin.TopRight), ("左下", ScaleOrigin.BottomLeft) ] for name, origin in items: item = MyItem(scale_origin=origin) layout.addWidget(item, Qt.AlignCenter) label = QLabel(name) layout.addWidget(label, Qt.AlignCenter) class MyItem(QLabel): def __init__(self, scale_origin=ScaleOrigin.TopLeft): super().__init__() self.base_size = QSize(30, 30) self.scale_factor = 10 self.scale_origin = scale_origin self.setMinimumSize(self.base_size) self.resize(self.base_size) self.setStyleSheet('background: blue') self._enlarged = False # 创建并行动画组,同步尺寸和位置动画 self.anim_group = QParallelAnimationGroup() # 尺寸动画 self.size_anim = QPropertyAnimation(self, b'size') self.size_anim.setDuration(200) self.anim_group.addAnimation(self.size_anim) # 位置动画 self.pos_anim = QPropertyAnimation(self, b'pos') self.pos_anim.setDuration(200) self.anim_group.addAnimation(self.pos_anim) def enterEvent(self, event): self._enlarged = False self.start_scale_anim() def leaveEvent(self, event): self._enlarged = True self.start_scale_anim() def start_scale_anim(self): if self._enlarged: target_size = self.base_size else: target_size = QSize(self.base_size.width() * self.scale_factor, self.base_size.height() * self.scale_factor) # 计算位置偏移量,让指定原点保持不动 current_pos = self.pos() current_size = self.size() dx = 0 dy = 0 if self.scale_origin == ScaleOrigin.TopCenter: dx = (current_size.width() - target_size.width()) / 2 elif self.scale_origin == ScaleOrigin.TopRight: dx = current_size.width() - target_size.width() elif self.scale_origin == ScaleOrigin.BottomLeft: dy = current_size.height() - target_size.height() elif self.scale_origin == ScaleOrigin.BottomCenter: dx = (current_size.width() - target_size.width()) / 2 dy = current_size.height() - target_size.height() elif self.scale_origin == ScaleOrigin.BottomRight: dx = current_size.width() - target_size.width() dy = current_size.height() - target_size.height() target_pos = QPoint(current_pos.x() + dx, current_pos.y() + dy) # 设置动画目标值 self.size_anim.setEndValue(target_size) self.pos_anim.setEndValue(target_pos) self.anim_group.start() if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() app.exec()
关键实现说明
- 定义
ScaleOrigin枚举,方便指定不同的缩放原点。 - 使用
QParallelAnimationGroup同时动画控件的size和pos属性,确保缩放和位置调整同步进行,避免卡顿。 - 根据选定的缩放原点,计算位置偏移量:比如选择顶部中心时,缩放后控件的水平中点要和原位置中点重合,所以需要向左偏移(原宽度-新宽度)/2的距离;选择右上时,需要向左偏移(原宽度-新宽度)的距离,垂直位置不变。
- 进入/离开事件中切换缩放状态,触发对应的动画。
内容的提问来源于stack exchange,提问作者coder
相关产品推荐
相关产品推荐

